使用並查集尋找時,如果尋找次數很多,那麼使用樸素版的尋找方式肯定要逾時。比如,有一百萬個元素,每次都從第一百萬個開始找,這樣一次運算就是10^6,如果程式要求尋找個一千萬次,這樣下來就是10^13,肯定要出問題的。
這是樸素尋找的代碼,適合資料量不大的情況:
int findx(int x){ int r=x; while(parent[r] !=r) r=parent[r]; return r;}
下面是採用路徑壓縮的方法尋找元素:
int find(int x) //尋找x元素所在的集合,回溯時壓縮路徑{ if (x != parent[x]) { parent[x] = find(parent[x]); //回溯時的壓縮路徑 } //從x結點搜尋到祖先結點所經過的結點都指向該祖先結點 return parent[x];}
上面是一採用遞迴的方式壓縮路徑, 但是,遞迴壓縮路徑可能會造成溢出棧,我曾經因為這個RE了n次,下面我們說一下非遞迴方式進行的路徑壓縮:
int find(int x){ int k, j, r; r = x; while(r != parent[r]) //尋找跟節點 r = parent[r]; //找到跟節點,用r記錄下 k = x; while(k != r) //非遞迴路徑壓縮操作 { j = parent[k]; //用j暫存parent[k]的父節點 parent[k] = r; //parent[x]指向跟節點 k = j; //k移到父節點 } return r; //返回根節點的值 }
使用並查集尋找時,如果尋找次數很多,那麼使用樸素版的尋找方式肯定要逾時。比如,有一百萬個元素,每次都從第一百萬個開始找,這樣一次運算就是10^6,如果程式要求尋找個一千萬次,這樣下來就是10^13,肯定要出問題的。
這是樸素尋找的代碼,適合資料量不大的情況:
int findx(int x){ int r=x; while(parent[r] !=r) r=parent[r]; return r;}
下面是採用路徑壓縮的方法尋找元素:
int find(int x) //尋找x元素所在的集合,回溯時壓縮路徑{ if (x != parent[x]) { parent[x] = find(parent[x]); //回溯時的壓縮路徑 } //從x結點搜尋到祖先結點所經過的結點都指向該祖先結點 return parent[x];}
上面是一採用遞迴的方式壓縮路徑, 但是,遞迴壓縮路徑可能會造成溢出棧,我曾經因為這個RE了n次,下面我們說一下非遞迴方式進行的路徑壓縮:
int find(int x){ int k, j, r; r = x; while(r != parent[r]) //尋找跟節點 r = parent[r]; //找到跟節點,用r記錄下 k = x; while(k != r) //非遞迴路徑壓縮操作 { j = parent[k]; //用j暫存parent[k]的父節點 parent[k] = r; //parent[x]指向跟節點 k = j; //k移到父節點 } return r; //返回根節點的值 }