@(文章目錄)數組
對於並查集(不相交集合)
,不少人會感到很陌生
,沒聽過或者不是特別瞭解。實際上並查集是一種挺高效的數據結構。實現簡單,只是全部元素統一聽從一個規律
因此讓辦事情的效率高效起來。數據結構
對於定意義,百科上這麼定義的:函數
並查集,在一些有N個元素的集合應用問題中,咱們一般是在開始時讓每一個元素構成一個單元素的集合,而後按必定順序將屬於同一組的元素所在的集合合併,其間要反覆查找一個元素在哪一個集合中。其特色是看似並不複雜,但數據量極大,若用正常的數據結構來描述的話,每每在空間上過大,計算機沒法承受;即便在空間上勉強經過,運行的時間複雜度也極高,根本就不可能在比賽規定的運行時間(1~3秒)內計算出試題須要的結果,只能用並查集來描述。學習
並查集是一種樹型的數據結構
,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。經常在使用中以森林來表示。this
各自爲根
join(a,b)
操做。a,b兩個集合
合併。注意這裏的a,並非a,b合併,而是a,b的集合合併。這就派生了一些狀況:data[a]=b
;同時爲了表示這個集合有多少個,本來-1
的b再次-1.即data[b]=-2
.表示以b爲父親的節點有|-2|個。不能直接操做a,b
(由於a,b可能已經指向別人了.)那麼咱們只能操做a,b的祖先。由於a,b的祖先是沒有指向的(即數據爲負值表示大小)。那麼他們首先一個負值要加到另一個上面去。另外這個數值要變成指向的那個表示聯繫。對於上述你可能會有疑問:3d
節點根祖先的結果是否相同便可
。由於只有根的數值是負的,而其餘都是正數表示指向的元素。因此只須要一直尋找直到不爲正數進行比較便可
!因此咱們一般是:小數指向大樹(或者低樹指向高樹),這個使得查詢效率可以增長!
固然,在高度和數量的選擇上,還須要你本身選擇和考慮。code
每次查詢,自下向上。當咱們調用遞歸的時候,能夠順便壓縮路徑,由於咱們查找一個元素其實只須要直到它的祖先,因此當他距離祖先近那麼下次查詢就很快
。而且壓縮路徑的代價並不大!
blog
並查集實現起來較爲簡單,直接貼代碼!遞歸
package 並查集不想交集合; import java.util.Scanner; public class DisjointSet { static int tree[]=new int[100000];//假設有500個值 public DisjointSet() {set(this.tree);} public DisjointSet(int tree[]) { this.tree=tree; set(this.tree); } public void set(int a[])//初始化全部都是-1 有兩個好處,這樣他們指向-1說明是本身,第二,-1表明當前森林有-(-1)個 { int l=a.length; for(int i=0;i<l;i++) { a[i]=-1; } } public int search(int a)//返回頭節點的數值 { if(tree[a]>0)//說明是子節點 { return tree[a]=search(tree[a]);//路徑壓縮 } else return a; } public int value(int a)//返回a所在樹的大小(個數) { if(tree[a]>0) { return value(tree[a]); } else return -tree[a]; } public void union(int a,int b)//表示 a,b所在的樹合併 { int a1=search(a);//a根 int b1=search(b);//b根 if(a1==b1) {System.out.println(a+"和"+b+"已經在一棵樹上");} else { if(tree[a1]<tree[b1])//這個是負數,爲了簡單減小計算,不在調用value函數 { tree[a1]+=tree[b1];//個數相加 注意是負數相加 tree[b1]=a1; //b樹成爲a的子樹,直接指向a; } else { tree[b1]+=tree[a1];//個數相加 注意是負數相加 tree[a1]=b1; //b樹成爲a的子樹,直接指向a; } } } public static void main(String[] args) { DisjointSet d=new DisjointSet(); d.union(1,2); d.union(3,4); d.union(5,6); d.union(1,6); d.union(22,24); d.union(3,26); d.union(36,24); System.out.println(d.search(6)); //頭 System.out.println(d.value(6)); //大小 System.out.println(d.search(22)); //頭 System.out.println(d.value(22)); //大小 } }
並查集還普遍用於迷宮遊戲
中,下面有機會能夠介紹用並查集實現一個走迷宮小遊戲。你們歡迎關注!筆者學習資源
也放置公衆號和你們一塊兒分享!