這篇文章主要介紹了C++并查集的常用操作有哪些的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇C++并查集的常用操作有哪些文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
成都創(chuàng)新互聯(lián)公司專注于五華網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供五華營(yíng)銷型網(wǎng)站建設(shè),五華網(wǎng)站制作、五華網(wǎng)頁(yè)設(shè)計(jì)、五華網(wǎng)站官網(wǎng)定制、小程序開發(fā)服務(wù),打造五華網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供五華網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
并查集是一種多叉樹,用于處理不相交的集合的合并與查詢問(wèn)題(判斷)。
通俗理解:在日常生活中,我們會(huì)因?yàn)槟硞€(gè)人是自己的朋友,哪怕是朋友的朋友也是有朋友,會(huì)給予通融、 偏袒。而并查集的基本概念,就是判斷某兩個(gè)集合是否是“朋友”關(guān)系,并讓兩個(gè)集合成為“朋友”
初始化:每個(gè)結(jié)點(diǎn)單獨(dú)作為一個(gè)集合
查詢:求元素所在的集合的代表元素,即根結(jié)點(diǎn)
合并:將兩個(gè)元素所在的集合,合并為一個(gè)集合
合并之前,應(yīng)先判斷兩個(gè)元素是否屬于同一集合,用上面的“查詢”來(lái)實(shí)現(xiàn)
初始化:初始的時(shí)候每個(gè)結(jié)點(diǎn)各自為一個(gè)集合,father[i]表示結(jié)點(diǎn) i 的父親結(jié)點(diǎn),如果 father[i]=i,我們認(rèn)為這個(gè)結(jié)點(diǎn)是當(dāng)前集合根結(jié)點(diǎn)(開始時(shí)每個(gè)節(jié)點(diǎn)根節(jié)點(diǎn)是他自己)。
void init() { for (int i = 1; i <= n; ++i) { father[i] = i; } }
查找:查找結(jié)點(diǎn)所在集合的根結(jié)點(diǎn),結(jié)點(diǎn) x 的根結(jié)點(diǎn)必然也是其父親結(jié)點(diǎn)的根結(jié)點(diǎn)(像是有遞歸的樣子)。
int get(int x) { if (father[x] == x) { // x 結(jié)點(diǎn)就是根結(jié)點(diǎn) return x; } return get(father[x]); // 如果該節(jié)點(diǎn)不是根節(jié)點(diǎn),繼續(xù)尋找父結(jié)點(diǎn)的根結(jié)點(diǎn) }
合并:將兩個(gè)元素所在的集合合并在一起,通常來(lái)說(shuō),合并之前先判斷兩個(gè)元素是否屬于同一集合。
void hebing(int x, int y) { x = find(x); y = find(y); if (x != y) { // 不在同一個(gè)集合 father[y] = x;//將根節(jié)點(diǎn)合并 } }
上面三個(gè)操作是并查集常用的操作
前面的并查集的復(fù)雜度實(shí)際上在有些極端情況會(huì)很慢。比如樹的結(jié)構(gòu)正好是一條鏈,那么最壞情況下,每次查詢的復(fù)雜度達(dá)到了O(n) 。這并不是我們期望的結(jié)果。路徑壓縮的思想是,我們只關(guān)心每個(gè)結(jié)點(diǎn)的父結(jié)點(diǎn),而并不太關(guān)心樹的真正的結(jié)構(gòu)(遞歸查找相當(dāng)浪費(fèi)時(shí)間)如下:
當(dāng)想去訪問(wèn)6的根節(jié)點(diǎn)時(shí),要訪問(wèn)5的根節(jié)點(diǎn),想去訪問(wèn)5的根節(jié)點(diǎn),又要去訪問(wèn)4的根節(jié)點(diǎn)..........以此類推,此時(shí)并查集退化為線性。
這樣我們?cè)谝淮尾樵兊臅r(shí)候,可以把查詢路徑上的所有結(jié)點(diǎn)的father[i]都賦值成為根結(jié)點(diǎn)。只需要在我們之前的查詢函數(shù)上面進(jìn)行很小的改動(dòng)
int findf(int k) { if(f[k] == k) return k; return f[k] = findf(f[k]); //后來(lái)更新的點(diǎn)的根節(jié)點(diǎn)直接為最開始的點(diǎn),一步找到總根節(jié)點(diǎn)。 }
關(guān)于“C++并查集的常用操作有哪些”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“C++并查集的常用操作有哪些”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。