日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

并查集+基础知识点详解

發(fā)布時(shí)間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并查集+基础知识点详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

并查集概念

并查集單看名字大家也能猜到這個(gè)算法的作用,是用來(lái)對(duì)集合進(jìn)行合并和查找操作

并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不相交集合(Disjoint Sets)的合并及查詢問(wèn)題。——來(lái)自百度百科

就是將原本不一樣的集合,但是由于某種關(guān)系有了聯(lián)系,把他合并成同一個(gè)集合,就是實(shí)現(xiàn)一個(gè)這樣的功能。

基本操作

并查集是一種非常簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),(我是說(shuō)它的算法實(shí)現(xiàn)簡(jiǎn)單)它主要涉及兩個(gè)基本操作,分別為:
A.合并: 合并兩個(gè)不相交集合
B.查找: 去判斷兩個(gè)元素是否屬于同一個(gè)集合
接下來(lái),我會(huì)用并查集的圖形解釋來(lái)看下如何實(shí)現(xiàn)這兩個(gè)基本操作。
1.可以看到這里有六個(gè)小球,他們代表六個(gè)不一樣的元素,用數(shù)組來(lái)表示他們,給他們附上值,來(lái)代表不一樣的集合

2.現(xiàn)在我來(lái)給他們一些聯(lián)系,然后可以根據(jù)聯(lián)系進(jìn)行集合的一個(gè)合并,隨機(jī)得到一個(gè)樹狀結(jié)構(gòu)

只要是能通過(guò)關(guān)系串聯(lián)起來(lái)的,不管是直接聯(lián)系還是間接聯(lián)系,元素通過(guò)兩兩之間的關(guān)系串聯(lián)起來(lái),把他們都?xì)w到同一個(gè)集合。那么如何判斷兩個(gè)元素是否屬于一個(gè)集合呢?

我們可以在每個(gè)集合內(nèi)確定一個(gè)祖宗節(jié)點(diǎn),你們可以認(rèn)為是一個(gè)特殊點(diǎn),作為參照。這樣,兩個(gè)集合只要互相確認(rèn)自己的祖宗節(jié)點(diǎn)是不是同一個(gè),就可以確定關(guān)系了。

但是還有問(wèn)題啊,目前我們只知道直接的聯(lián)系,那么我們就需要對(duì)集合進(jìn)行操作,形成樹狀結(jié)構(gòu),祖宗節(jié)點(diǎn)就是根節(jié)點(diǎn),下面分別是二級(jí)、三級(jí)…。每個(gè)人只要記住自己的上級(jí)是誰(shuí)就行了。那么判斷是否屬于同一個(gè)集合,只要一層層向上查找,直到最高層,就可以在短時(shí)間內(nèi)確定了。由于我們關(guān)心的只是兩個(gè)元素是否在同一個(gè)集合的,至于他們是如何通過(guò)關(guān)系相關(guān)聯(lián)的,以及每個(gè)圈子內(nèi)部的結(jié)構(gòu)是怎樣的,甚至祖宗節(jié)點(diǎn)是誰(shuí),都不重要了,就可以隨機(jī)確定上下級(jí)關(guān)系
3.我們最終經(jīng)過(guò)處理,實(shí)現(xiàn)的是如圖所示

接下來(lái)是對(duì)代碼實(shí)現(xiàn)的一個(gè)講解

一般來(lái)說(shuō),一個(gè)并查集代碼實(shí)現(xiàn)對(duì)應(yīng)三個(gè)重要步驟:初始化+查找根結(jié)點(diǎn)函數(shù)+合并集合函數(shù)

【初始化】

這個(gè)集合的類別pre(其實(shí)就是一個(gè)指針,用來(lái)指示這個(gè)集合屬于那一類,合并過(guò)后的集合,他們的pre指向的最終值一定是相同的)
初始化的時(shí)候,每一個(gè)集合的pre都是這個(gè)集合自己的標(biāo)號(hào)。沒(méi)有跟它同類的集合,那么這個(gè)集合的源頭只能是自己了。

int pre[max]; //集合index的類別,或者用parent表示 //初始化集合 void init() { for(int i=1;i<=n;i++)pre[i]=i; //一個(gè)集合的pre都是這個(gè)集合自己的標(biāo)號(hào)。沒(méi)有跟它同類的集合,那么這個(gè)集合的源頭只能是自己了。 }

【查找函數(shù)】

就是找到pre指針的源頭,可以把函數(shù)命名為find,如果集合的pre等于集合的編號(hào)(即還沒(méi)有被合并或者沒(méi)有同類),那么自然返回自身編號(hào)。 如果不同(即經(jīng)過(guò)合并操作后指針指向了源頭(合并后選出的rank高的集合))那么就可以調(diào)用遞歸函數(shù),如下面的代碼:

//查找集合i(一個(gè)元素是一個(gè)集合)的源頭(遞歸實(shí)現(xiàn)) int Find(int i) {//如果集合i的父親是自己,說(shuō)明自己就是源頭,返回自己的標(biāo)號(hào)if(pre[i]==i)return pre[i];//否則查找集合i的父親的源頭return Find(pre[i]); }

遞歸,這個(gè)已經(jīng)講過(guò)很多次,這里就不再多講,大家可以結(jié)合瀏覽器的后退功能,如果你想追溯源頭,你就一直回溯,就能找到。

【合并】

將兩個(gè)元素所在的集合合并為一個(gè)集合。
通常來(lái)說(shuō),合并之前,應(yīng)先判斷兩個(gè)元素是否屬于同一集合,這可用上面的"查找"操作實(shí)現(xiàn)。那么我們?nèi)绾魏喜蓚€(gè)不相交集合(Union(x,y))
合并操作很簡(jiǎn)單:先設(shè)置一個(gè)數(shù)組pre[x],表示x的“父親”的編號(hào)。那么,合并兩個(gè)不相交集合的方法就是,找到其中一個(gè)集合祖宗節(jié)點(diǎn),將另外一個(gè)集合的祖宗節(jié)點(diǎn)的父親指向它。

int gets(int a,int b){int x=Find(a);int y=Find(b);if(x!=y)pre[y]=x;}

算法描述總結(jié)

關(guān)鍵特征:
①用集合中的某個(gè)元素來(lái)代表這個(gè)集合~~,該元素稱為集合的代表元;~~
②構(gòu)成了一個(gè)以代表元素為根的樹形結(jié)構(gòu);
③對(duì)于每一個(gè)元素 pre[x]指向x在樹形結(jié)構(gòu)上的父親節(jié)點(diǎn)。如果x是根節(jié)點(diǎn),則令pre[x] = x;
④對(duì)于查找操作,假設(shè)需要確定x所在的的集合,也就是確定集合的代表元。可以沿著pre[x]不斷在樹形結(jié)構(gòu)中向上移動(dòng),直到到達(dá)根節(jié)點(diǎn)。
判斷兩個(gè)元素是否屬于同一集合,只需要看他們的代表元是否相同即可。
用途:
1、維護(hù)無(wú)向圖的連通性。支持判斷兩個(gè)點(diǎn)是否在同一連通塊內(nèi),和判斷增加一條邊是否會(huì)產(chǎn)生環(huán)。
2、用在求解最小生成樹的Kruskal算法里。
如果還有哪里我講的不清楚,或是有疑問(wèn),歡迎私聊我,我會(huì)為你們解答。

貼上其他博客講解并查集的1 2 3 4

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的并查集+基础知识点详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。