在一些應用問題中,需將n個不同的元素劃分成一組不相交的集合。開始時,每個元素組成乙個單元集合,然後按一定順序將屬於同一組元素的集合合併。其間要反覆用到查詢某個元素屬於哪個集合的運算。適合於描述這類問題的抽象資料型別稱為並查集。
ufunion(a,b,u):將並查集u中的集合a和b合併,其結果取名為a或b。
uffind(e):找出包含元素e的集合,並返回該集合的名字。
確定集合上的等價關係。
在並查集中需要兩種型別的引數:集合名字的型別和元素的型別。
用陣列實現的並查集可描述如下。
其中,整數n是集合中元素的個數,components是表示元素及其所屬子集關係的陣列,components[x]表示元素x當前所屬的集合的名字。
函式ufinit(size)將components初始化成大小為size的單元集合。
uffind(e)的值就是comonents[e]。
採用樹結構實現並查集的基本思想是:每個集合用一棵樹來表示,樹的結點用於儲存集合中的元素名和乙個指向其父結點的指標,樹根結點處的元素代表該樹所表示的集合,利用對映可以找到集合中元素所對應的樹結點。
父結點陣列是實現上述樹結構的有效方法。
其中,parent是表示樹結構的父結點陣列。元素x的父結點為parent[x]。
函式ufinit(size)將每個元素初始化為一棵單結點樹。
uffind(e,u)運算就是從元素e相應的結點走到樹根處,找出所在集合的名字。
ufunion(i,j,u)合併兩個集合。只要將表示乙個集合的樹的樹根改為表示另乙個集合的樹的樹根的兒子。
改進的並查集結構中增加乙個根結點陣列root,用來記錄樹的根結點。當元素e所在結點不是根結點時,root[e]=0,parent[e]表示其父結點;當元素e所在結點是根結點時,root[e]=1,parent[e]的值是樹中結點個數。
函式ufinit(size)將每個元素初始化為一棵單結點樹。
uffind(e,u)運算從運算e相應的結點走到樹根處,找出所在集合的名字。
ufunion(i,j,u)運算將小樹合併到大樹上。
用父結點陣列實現並查集ufset時,根結點陣列root和父結點陣列parent都是動態分配的,需要適時釋放所分配的空間。
加速並查集運算的另乙個辦法是採用路徑壓縮技術。在執行ufind運算時, 實際上找到了從乙個結點到樹根的一條路徑。路徑壓縮是把這條路上的所有結點都改為樹根的兒子。實現路徑壓縮的最簡單方法是在這條路上走兩次,第一次找到樹根,第二次將路上所有結點的父結點都改為樹根。
路徑壓縮並不影響ufunion運算的時間,它仍然只要o(1)時間,但是路徑壓縮大大地加速了uffind運算。
這裡講解以不相交的集合為基礎的抽象資料型別並查集及其實現方法。
並查集支援的主要集合運算是集合查詢和集合合併運算。
用陣列容易實現並查集,但其集合合併運算效率較低。
用樹結構實現並查集使得集合合併運算只需要o(1)時間。在最壞情況下,合併運算可能使n個結點的樹退化成一條鏈。
在這種情況下, 對所有元素各執行一次uffind運算將耗時o(n) 。
為了克服這個缺點, 在合併時採用將小樹合併到大樹的策略可使每次執行uffind運算不超過o(logn)時間。
進一步採用路徑壓縮技術可以使執行ufind需要的平均時間降至0(a(n) ) 。
C語言資料結構拉練 並查集
資料結構 結構定義 結構操作 結構定義 陣列 尺寸 數值相同的陣列索引標記為一類 include include typedef struct unionset unionset 結構操作 初始化 清除 unionset init int n return u void clear unionset...
資料結構 並查集
並查集,顧名思義,合併 查詢 集合 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。對於概念等等的這裡不再贅述,直接講解應用。應用1 判斷圖中有多少聯通分量 或者圖是否聯通 聯通分量 1 hdu 1213 應用2 判斷圖是否...
資料結構 並查集
time limit 1000ms memory limit 65536k 某城市有n個人,現在給定關於n個人的m條資訊,m條資訊是兩個人在同乙個小區,根據所給資訊,判斷這個城市最多可能有多少個小區。n個人編號為1 n。多組輸入。每組第一行有兩個整數n,m 2 n 50000,0 m n 2 接下來...