并查集+基础知识点详解
并查集概念
并查集單看名字大家也能猜到這個算法的作用,是用來對集合進行合并和查找操作
并查集是一種樹型的數據結構,用于處理一些不相交集合(Disjoint Sets)的合并及查詢問題。——來自百度百科
就是將原本不一樣的集合,但是由于某種關系有了聯系,把他合并成同一個集合,就是實現一個這樣的功能。
基本操作
并查集是一種非常簡單的數據結構,(我是說它的算法實現簡單)它主要涉及兩個基本操作,分別為:
A.合并: 合并兩個不相交集合
B.查找: 去判斷兩個元素是否屬于同一個集合
接下來,我會用并查集的圖形解釋來看下如何實現這兩個基本操作。
1.可以看到這里有六個小球,他們代表六個不一樣的元素,用數組來表示他們,給他們附上值,來代表不一樣的集合
2.現在我來給他們一些聯系,然后可以根據聯系進行集合的一個合并,隨機得到一個樹狀結構
只要是能通過關系串聯起來的,不管是直接聯系還是間接聯系,元素通過兩兩之間的關系串聯起來,把他們都歸到同一個集合。那么如何判斷兩個元素是否屬于一個集合呢?
我們可以在每個集合內確定一個祖宗節點,你們可以認為是一個特殊點,作為參照。這樣,兩個集合只要互相確認自己的祖宗節點是不是同一個,就可以確定關系了。
但是還有問題啊,目前我們只知道直接的聯系,那么我們就需要對集合進行操作,形成樹狀結構,祖宗節點就是根節點,下面分別是二級、三級…。每個人只要記住自己的上級是誰就行了。那么判斷是否屬于同一個集合,只要一層層向上查找,直到最高層,就可以在短時間內確定了。由于我們關心的只是兩個元素是否在同一個集合的,至于他們是如何通過關系相關聯的,以及每個圈子內部的結構是怎樣的,甚至祖宗節點是誰,都不重要了,就可以隨機確定上下級關系
3.我們最終經過處理,實現的是如圖所示
接下來是對代碼實現的一個講解
一般來說,一個并查集代碼實現對應三個重要步驟:初始化+查找根結點函數+合并集合函數
【初始化】
這個集合的類別pre(其實就是一個指針,用來指示這個集合屬于那一類,合并過后的集合,他們的pre指向的最終值一定是相同的)
初始化的時候,每一個集合的pre都是這個集合自己的標號。沒有跟它同類的集合,那么這個集合的源頭只能是自己了。
【查找函數】
就是找到pre指針的源頭,可以把函數命名為find,如果集合的pre等于集合的編號(即還沒有被合并或者沒有同類),那么自然返回自身編號。 如果不同(即經過合并操作后指針指向了源頭(合并后選出的rank高的集合))那么就可以調用遞歸函數,如下面的代碼:
//查找集合i(一個元素是一個集合)的源頭(遞歸實現) int Find(int i) {//如果集合i的父親是自己,說明自己就是源頭,返回自己的標號if(pre[i]==i)return pre[i];//否則查找集合i的父親的源頭return Find(pre[i]); }遞歸,這個已經講過很多次,這里就不再多講,大家可以結合瀏覽器的后退功能,如果你想追溯源頭,你就一直回溯,就能找到。
【合并】
將兩個元素所在的集合合并為一個集合。
通常來說,合并之前,應先判斷兩個元素是否屬于同一集合,這可用上面的"查找"操作實現。那么我們如何合并兩個不相交集合(Union(x,y))
合并操作很簡單:先設置一個數組pre[x],表示x的“父親”的編號。那么,合并兩個不相交集合的方法就是,找到其中一個集合祖宗節點,將另外一個集合的祖宗節點的父親指向它。
算法描述總結
關鍵特征:
①用集合中的某個元素來代表這個集合~~,該元素稱為集合的代表元;~~
②構成了一個以代表元素為根的樹形結構;
③對于每一個元素 pre[x]指向x在樹形結構上的父親節點。如果x是根節點,則令pre[x] = x;
④對于查找操作,假設需要確定x所在的的集合,也就是確定集合的代表元。可以沿著pre[x]不斷在樹形結構中向上移動,直到到達根節點。
判斷兩個元素是否屬于同一集合,只需要看他們的代表元是否相同即可。
用途:
1、維護無向圖的連通性。支持判斷兩個點是否在同一連通塊內,和判斷增加一條邊是否會產生環。
2、用在求解最小生成樹的Kruskal算法里。
如果還有哪里我講的不清楚,或是有疑問,歡迎私聊我,我會為你們解答。
貼上其他博客講解并查集的1 2 3 4
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的并查集+基础知识点详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第三次作业:卷积神经网络基础
- 下一篇: 奔小康赚大钱 HDU - 2255( 二