學渣都能看懂的 並查集(高階版) 按秩歸併

2021-10-07 09:57:11 字數 1622 閱讀 2510

前置文章:學渣都能看懂的-並查集(快速掌握版)

比高度:

在並集時,我們直接讓v1的代表元素指向了v2的代表元素。並集操作多了以後,會導致集合樹的兩邊出現樹的高度不均衡的情況,從而查集時因路徑過長,查詢時間過長。

void

addclass

(int v1,

int v2)

//合併班級

為使樹兩邊能平衡,在合併前我們需要知道兩個集合的樹的高度,然後讓高度小的樹併入高度大的樹中,以實現樹的平衡。

我們用了乙個陣列來儲存每個元素指向的下乙個元素。我們在查集時,是用classmate[mate] == -1來判斷查到了代表元素。實際上,代表元素的classmate[mate]的值並不一定要等於某個特定的值,我們只需要讓其等於乙個非任意元素所處序號的值就行了。例如:我們總共有n個元素,按1-n給這些元素排列,查集時,非代表元素會跳轉到其他的非代表元素,直到跳轉到代表元素為止。我們可以讓代表元素在陣列中的位置儲存任意非序號內的元素。例:-1000,-1,0,n+1,n+100。

代表元素在陣列中儲存資料的靈活性使我們可以直接使用代表元素在陣列中的數值來表示高度。我們可以直接讓代表元素的陣列以-x的形式(其中x表示集合樹的高度)來表示該集合的樹的高度。

我們先將陣列全部初始化為-1,再在並集中加入對樹的高度高低的判斷與選擇

for

(int i =

1; i <= vnum; i++

)//初始化,還未合併班級,每個班只有乙個人,每個人都是班長,每個班的集合樹的高度都為1

classmate[i]=-

1;

void

addclass

(int v1,

int v2)

//合併班級

}

比規模:但是平衡的樹不一定在查詢起來最快,當其他分支的元素數量遠大於高度最高的分支的元素數量時,平衡的樹會使查詢資料變長。所以對於某些資料,我們可以讓classmate陣列中代表元素位置的資料儲存-x(x為集合元素的數量)。(這樣我們順便能知道集合裡元素的數量

//合併班級

else

//v1所在集合樹的元素數量多

}

當然我們一般難以辨別到底是用比高度還是比規模,在這裡我推薦用功能性更強的比規模(可以獲得集合中元素的個數)。按秩歸併和路徑壓縮是兩種對並查集的優化方法,其中路徑壓縮優化效率更高。在初學並查集時,路徑壓縮是一定要寫的,不然資料量一大就會超時;而按秩歸併有的老師不一定會教,所以我將按秩歸併放在了高階版。

推薦免費課程:浙江大學-資料結構-集合的簡化表示(往後看4節)

傻子都能看懂的並查集入門

其實並查集顧名思義就是有 合併集合 和 查詢集合 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節點。如果x是根...

傻子都能看懂的並查集入門

其實並查集顧名思義就是有 合併集合 和 查詢集合中的元素 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節點。如...

傻子都能看懂的並查集入門

其實並查集顧名思義就是有 合併集合 和 查詢集合中的元素 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節點。如...