六版並查集

2021-09-25 15:48:18 字數 4262 閱讀 4688

我們以前學的都是由父親節點指向孩子節點,並查集和原來的相反,由孩子節點指向父親節點主要用於處理連線問題和路徑問題,網路中的節點的連線狀態,數學中集合類的實現 ,我們不關心具體的元素是誰我們有個連線操作和並操作,具體的實現**如下

`public inte***ce uf

我們首先需要乙個陣列,把它命名為id,然後我們在進行編號,判斷是否連線就是判斷倆個id是不是同一編號。

具體的實現**:

private int id;

public unionfind1(int size)

} @override

public int getsize()

private int find(int p)

return id[p];

} //檢視元素p和元素q是否所屬乙個集合

@override

public boolean isconnected(int p ,int q)

//合併元素p和元素q所屬集合

@override

public void unionelements(int p,int q)

for(int i = 0; i < id.length; i++)

} }

每乙個節點都是根節點,都指向自己,union就是讓parent的編是多少 然後再指向對應的節點,以此類推如果編號和parent相等,那麼,就讓節點指向對應編號的根節點

具體的實現**如下

private int parent;

public unionfind2(int size)

} @override

public int getsize()

//查詢過程,查詢元素p所對應的集合編號

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

private int find(int p)

while(p != parent[p])

return p;

} //檢視元素p和元素q是否屬於乙個集合

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

@override

public boolean isconnected(int p,int q)

//合併元素p和元素q所屬的集合

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

@override

public void unionelements(int p,int q)

parent[proot] = qroot;

}

我們由於並查集不考慮大小,所以我們一直連線,深度會不斷增加,極端時,有可能變成乙個鍊錶,因此我們需要基於每棵樹中節點的大小來進行合併。具體的實現**如下

private int parent;

private int sz;//sz[i]表示以i為根的集合中的元素個數

public unionfind3(int size)

} @override

public int getsize()

//查詢過程,查詢元素p所對應的集合編號

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

private int find(int p)

while(p != parent[p])

return p;

} //檢視元素p和元素q是否屬於乙個集合

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

@override

public boolean isconnected(int p,int q)

//合併元素p和元素q所屬的集合

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

@override

public void unionelements(int p,int q)

//根據元素所在數的元素個數不同判斷合併方向

//將元素個數少的集合合併到元素個數多的集合上

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

}

基於rank的優化(根據根節點的深度來進行合併)我們要注意只有在倆集合的深度相等時後才進行rank的維護(因為只有乙個根節點)具體的實現**如下:

private int parent;

private int rank;//rank[i]表示以i為根的集合所表示樹的層數

public unionfind4(int size)

} @override

public int getsize()

//查詢過程,查詢元素p所對應的集合編號

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

private int find(int p)

while(p != parent[p])

return p;

} //檢視元素p和元素q是否屬於乙個集合

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

@override

public boolean isconnected(int p,int q)

//合併元素p和元素q所屬的集合

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

@override

public void unionelements(int p,int q)

//根據元素所在樹的rank不同判斷合併方向

//將rank低的集合合併到rank高的集合上

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

}

路徑壓縮優化並查集(讓節點指向節點父親的父親節點)具體的實現**如下

private int parent;

private int rank;//rank[i]表示以i為根的集合所表示樹的層數

public unionfind5(int size)

} @override

public int getsize()

//查詢過程,查詢元素p所對應的集合編號

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

private int find(int p)

while(p != parent[p])

return p;

} //檢視元素p和元素q是否屬於乙個集合

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

@override

public boolean isconnected(int p,int q)

//合併元素p和元素q所屬的集合

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

@override

public void unionelements(int p,int q)

//根據元素所在樹的rank不同判斷合併方向

//將rank低的集合合併到rank高的集合上

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

}

使用遞迴方法進行路徑壓縮優化並查集,以至於最後都指向根節點,具體的實現**如下

private int parent;

private int rank;//rank[i]表示以i為根的集合所表示樹的層數

public unionfind6(int size)

} @override

public int getsize()

//查詢過程,查詢元素p所對應的集合編號

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

private int find(int p)

if(p != parent[p])

return parent[p];

} //檢視元素p和元素q是否屬於乙個集合

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

@override

public boolean isconnected(int p,int q)

//合併元素p和元素q所屬的集合

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

@override

public void unionelements(int p,int q)

//根據元素所在樹的rank不同判斷合併方向

//將rank低的集合合併到rank高的集合上

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

}

以上就是對六種種並查集的理解,不喜勿噴!謝謝!

並查集 並查集

本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...

並查集入門(普通並查集 帶刪除並查集 關係並查集)

什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...

並查集,帶權並查集

題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...