演算法與資料結構系列之 並查集 下

2021-09-25 03:18:01 字數 1956 閱讀 5570

接著上篇介紹並查集的優化方法

3.路徑壓縮

壓縮過程:每次執行查詢方法時,都執行以下parent[i] = parent[parent[i]],也就是每次查詢時先判斷要查詢的節點的父節點是否是根節點,不是的話讓當前節點指向當前節點的父節點的父節點,完成一次壓縮,如果要查詢的節點的父節點的父節點還不是根節點,就繼續向上遍歷,直到要查詢的節點的父節點的父節點是根節點。

**實現:

public class unionfind5 implements uf 

}@override

public int getsize()

//查詢i對應的集合編號

//時間複雜度為o(h),h為樹的高度

private int find(int i)

return i;

}@override

public boolean isconnected(int p, int q)

//合併操作

//時間複雜度為o(h),h為樹的高度

@override

public void unionelements(int p, int q)

else if (rank[qroot] < rank[proot])

else}}

效能測試:

測試**

public class test 

for (int i = 0; i < m; i++)

long endtime = system.nanotime();

return (endtime - starttime) / 1000000000.0;

}public static void main(string args)

}

執行結果

路徑壓縮後的效能有了顯著的提公升。

4.理想化的路徑壓縮

在上面介紹了理想化的路徑壓縮比價難實現,但是並不是不可以實現,我們完全可以借助遞迴方法把圖一中的第一棵樹壓縮成圖一中的第二棵樹的形狀,只是這種理想化的壓縮對效能提公升不了多小,甚至可能使效能稍微變差,因為遞迴呼叫是要耗費效能的。

**實現:

public class unionfind6 implements uf 

}@override

public int getsize()

//查詢i對應的集合編號

//時間複雜度為o(h),h為樹的高度

private int find(int i)

return parent[i];

}@override

public boolean isconnected(int p, int q)

//合併操作

//時間複雜度為o(h),h為樹的高度

@override

public void unionelements(int p, int q)

else if (rank[qroot] < rank[proot])

else}}

效能測試:

**同上,只加兩句

unionfind6 unionfind6 = new unionfind6(size);

system.out.println("unionfind6: " + testuf(unionfind6,m) + " s");

執行結果

資料結構與演算法之並查集

並查集結構可以用於 1 檢查兩個元素是否屬於同乙個集合 比如對於圖1這個例子來說,如果我們想要檢查節點d和節點e是否屬於同乙個集合,可以這樣操作 d節點往上找其父節點,一直往上找,直到某個節點的父節點是其本身,此時停止 找到了節點a e節點也按照相同的步驟往上找其父節點,找到節點a 如果這兩個節點往...

資料結構與演算法之並查集

並查集 union find 是一種高效的資料結構,主要的操作有 為方便敘述,把所有元素視作點,元素之間的關係視作線,存在聯絡便存在關係 需要注意的是,這裡的關係應當是1.自反的,2.對稱的,3.傳遞的 所謂合併,便是將兩個點之間 畫 一條線。又上邊的定義不難理解相連的若干點之間互相存在關係,這樣我...

演算法基礎之資料結構 並查集

題目 合併計算 一共有 n 個數,編號是 1 n,最開始每個數各自在乙個集合中。現在要進行 m 個操作,操作共有兩種 m a b,將編號為 a 和 b 的兩個數所在的集合合併,如果兩個數已經在同乙個集合中,則忽略這個操作 q a b,詢問編號為 a 和 b 的兩個數是否在同乙個集合中 輸入格式 第一...