1. 程式人生 > >資料結構學習 並查集講解(思路,時間複雜度)

資料結構學習 並查集講解(思路,時間複雜度)

1、  概述

並查集(Disjoint set或者Union-find set)是一種樹型的資料結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。

2、  基本操作

並查集是一種非常簡單的資料結構,它主要涉及兩個基本操作,分別為:

A. 合併兩個不相交集合

B. 判斷兩個元素是否屬於同一個集合

(1)       合併兩個不相交集合(Union(x,y))

合併操作很簡單:先設定一個數組Father[x],表示x的“父親”的編號。那麼,合併兩個不相交集合的方法就是,找到其中一個集合最父親的父親(也就是最久遠的祖先),將另外一個集合的最久遠的祖先的父親指向它。


上圖為兩個不相交集合,b圖為合併後Father(b):=Father(g)

(2)       判斷兩個元素是否屬於同一集合(Find_Set(x))

本操作可轉換為尋找兩個元素的最久遠祖先是否相同。可以採用遞迴實現。

3、  優化

(1)       Find_Set(x)時,路徑壓縮

尋找祖先時,我們一般採用遞迴查詢,但是當元素很多亦或是整棵樹變為一條鏈時,每次Find_Set(x)都是O(n)的複雜度。為了避免這種情況,我們需對路徑進行壓縮,即當我們經過”遞推”找到祖先節點後,”回溯”的時候順便將它的子孫節點都直接指向祖先,這樣以後再次Find_Set(x)時複雜度就變成O(1)了,如下圖所示。可見,路徑壓縮方便了以後的查詢。


(2)       Union(x,y)時,按秩合併

即合併的時候將元素少的集合合併到元素多的集合中,這樣合併之後樹的高度會相對較小。

4、  程式設計實現

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 int father[MAX];  
/* father[x]表示x的父節點*/ int rank[MAX];     /*rank[x]表示x的秩*/   void Make_Set(int x) { father[x] = x; //根據實際情況指定的父節點可變化 rank[x] = 0;   //根據實際情況初始化秩也有所變化 } /* 查詢x元素所在的集合,回溯時壓縮路徑*/ int Find_Set(int x) { if (x != father[x]) { father[x] = Find_Set(father[x]); //這個回溯時的壓縮路徑是精華 } return father[x]; } /* 按秩合併x,y所在的集合 下面的那個if else結構不是絕對的,具體根據情況變化 但是,宗旨是不變的即,按秩合併,實時更新秩。 */ void Union(int x, int y) { x = Find_Set(x); y = Find_Set(y); if (x == y) return; if (rank[x] > rank[y]) { father[y] = x; } else { if (rank[x] == rank[y]) { rank[y]++; } father[x] = y; } }

5、  複雜度分析

空間複雜度為O(N),建立一個集合的時間複雜度為O(1),N次合併M查詢的時間複雜度為O(M Alpha(N)),這裡Alpha是Ackerman函式的某個反函式,在很大的範圍內(人類目前觀測到的宇宙範圍估算有10的80次方個原子,這小於前面所說的範圍)這個函式的值可以看成是不大於4的,所以並查集的操作可以看作是線性的。具體複雜度分析過程見參考資料(3)。

6、  應用

並查集常作為另一種複雜的資料結構或者演算法的儲存結構。常見的應用有:求無向圖的連通分量個數,最近公共祖先(LCA),帶限制的作業排序,實現Kruskar演算法求最小生成樹等。

7、  參考資料

(3)       Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0-262-03293-7. Chapter 21: Data structures for Disjoint Sets, pp. 498–524.

————————————————————————————————————-

更多關於資料結構和演算法的介紹,請檢視:資料結構與演算法彙總

————————————————————————————————————-

相關推薦

資料結構學習 講解思路時間複雜

1、  概述 並查集(Disjoint set或者Union-find set)是一種樹型的資料結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。 2、  基本操作 並查集是一種非常簡單的資料結構,它主要涉及兩個基本操作,分別為: A. 合併兩個

資料結構09—— Union-Find

一、關於並查集 並查集(Union-Find)是一種樹型的資料結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。並查集(Union-Find)從名字可以看出,主要它涉及兩種基本操作:合併和查詢。這說明,初始時並查集中的元素是不相交的,經過一系列的基本操作(Union)

講解

-- 找我 這一 重新 detail 返回 變化 兩個人 之前 並查集是我暑假從高手那裏學到的一招,覺得真是太精妙的設計了。以前我無法解決的一類問題竟然可以用如此簡單高效的方法搞定。不分享出來真是對不起party了。(party:我靠,關我嘛事啊?我跟你很熟麽?) 來看一

noip提高組資料結構模板[,st表,樹狀陣列,線段樹]

/*資料結構*/ //並查集 for(int i=1;i<=n;i++) fa[i]=i;*** int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} //st表 for(int i=2;i<=n;i++) Log[i]=Lo

玩轉資料結構(18)--

並查集(Union Find) 一、概述 由孩子節點指向父親節點的樹結構,解決連線問題,如圖來判斷兩個點之間是否是連線的 並查集:可以快速判斷網路中節點間的連線狀態【網路:抽象概念,使用者之間形成的網路】可以高效回答連線問題的資料結構 對於一組資料,主要支援兩

資料結構】——

概念:所謂並查集,就是把一個集合合併再進行查詢。 並查集基本操作: 1、將a、b兩個元素合併在一個集合 2、查詢a、b是否在一個集合 那麼,我們這是就要思考:如何將每個元素合併在一個集合呢?它們之間是否存在著某個標誌? 很顯然,標誌是肯定要存在的。 首先,

*step3_資料結構_ACM HDU1272 小希的迷宮【

瘋狂WA題。 這道題就是一個簡單的並查集。 但是我在瘋狂WA題的過程中,個人覺得這道題還有點問題,首先,這道題沒有說清楚,有沒有對同一條邊輸入兩次的情況,在第一遍wa掉後,我打算解決這個問題,顯然,無果,因為測試資料沒那種情況。 在這道題應當收穫的教訓是,對這種簡單

資料結構

1.概述 英文:DisjointSet or(Union-find set),即“不相交集合”將編號分別為1…N的N個物件劃分為不相交集合,在每個集合中,選擇其中某個元素代表所在集合。 常見兩種操作: (1)合並兩個集合      (2)查找某元素屬於哪個集合 所以也成稱

Codeforces Round #541 (Div. 2)又稱dsu拓撲排序

每次 == auto else if microsoft 沒有 spa pan force #include<bits/stdc++.h>using namespace std;vector<int>g[2007];int fa[2007],vis[

資料結構十分鐘搞定時間複雜演算法的時間複雜【轉】

我們假設計算機執行一行基礎程式碼需要執行一次運算。 int aFunc(void) { printf("Hello, World!\n"); // 需要執行 1 次 return 0; // 需要執行 1 次 } 那麼上面這個

十分鐘搞定時間複雜演算法的時間複雜

我們假設計算機執行一行基礎程式碼需要執行一次運算。 int aFunc(void) { printf("Hello, World!\n"); // 需要執行 1 次 return 0; // 需要執行 1 次 } 那麼上面這個方法

常見排序演算法總結實現原理穩定使用場景時間複雜

快速排序是目前基於比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短;堆排序所需的輔助空間少於快速排序,並且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。若要求排序穩定,則可選用歸併排序。但本章介紹的從單個記錄起進行兩兩歸併的排序演算法並不值得提倡,通常可以

講解按秩合與路徑壓縮

ram == return n) style str fin bsp pre 自看。。。 借鑒自:https://blog.csdn.net/u011056504/article/details/51222494 1、路徑壓縮 void find(int x) {

數據結構_轉載

target blog 隨機 輸出 無法 增加 輸出結果 還需 class 一、問題引入 原題:杭電hdu1232暢通工程 題意:首先在地圖上給你若幹個城鎮,這些城鎮都可以看作點,然後告訴你哪些對城鎮之間是有道路直接相連的。最後要解決的是整幅圖的連通性問題。比如隨意給

——poj2236帶權

algorithm blog oid poj2236 stream 命令 net 最大 spa 題目:Wireless Network 題意:給定n臺已損壞計算機的位置和計算機最遠通信距離d,然後分別根據命令執行以下兩種操作: "O p" (1 <= p <=

【數據結構

tro 算法導論 src html target style 導論 span tony 【並查集】       為實現 在 不相交集合 上的操作 (1.合並兩個集合 2.查詢某個元素屬於哪個集合)而定義的一種數據結構      其實現有兩種方式:鏈表和有根樹   

【HDU 1272】小希的迷宮無向圖之回路問題

problem 沒有 現在 new 一行 回路 問題 ima namespace 描述 上次Gardon的迷宮城堡小希玩了很久(見Problem B),現在她也想設計一個迷宮讓Gardon來走。但是她設計迷宮的思路不一樣,首先她認為所有的通道都應該是雙向連通的,就是說如果

資料結構學習筆記------紅黑樹附c++程式碼

1、紅黑樹簡介 紅黑樹是二叉查詢樹的一種,其增刪改查的統計效能要優於AVL樹,查詢、插入、刪除演算法的複雜度都為O(log(n))。先附上紅黑樹這種資料結構的性質: 性質1、節點是紅色或黑色。 性質2、根節點是黑色。 性質3、每個葉節點(是指的空節點,nil節點)是黑色的。 性質4、

+二分POJ 2253

Description Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He

模板C++版

最簡單的並查集 hdu1232 #include <algorithm> #include <cstdio> #include <cstring> using nam