並查集的實現及優化

2021-08-22 04:45:29 字數 1338 閱讀 2608

並查集是一種用於在森林中判斷子圖數量及點的歸屬的資料結構,由於其特殊的路徑壓縮操作,使得這一過程可以異常地快。

並查集主要由乙個pre陣列以及兩個函式組成:find函式和join函式。

pre陣列表示每一節點的前驅,最終已完成的並查集,每乙個子圖的所有點只有乙個前驅(這也是其高效的原因),而初始化的並查集每乙個點都是自己的前驅。

find函式負責尋找乙個點的總前驅,比如:若有a->b->c->d這樣的鏈狀結構,a->b表示b是a的前驅,則在這個結構中,a的總前驅是d。

join函式負責將兩個子圖合併:給出任意兩個點,判斷他們是否分別屬於兩個子圖,若是,則找到他們的總前驅,將乙個變成另乙個的子點。

示例**;

int pre[maxn]

, rank[maxn]

;void

init

(int n)

intfind

(int x)

void

join

(int p1,

int p2)

並查集的最終效果是在查詢結構上將森林中每乙個圖變成有且僅有乙個根節點的樹,這樣,每乙個圖中所有點的前驅都是一樣的,大大方便了查詢判斷與子圖計數。

這裡的乙個優化(對「查」的優化):在用find函式尋找總前驅的過程中,若開始點位於一條長長的鏈上,則每次要從鏈上開始時,時間複雜度都是o(n),效率比較低,但是如果我們在尋找的同時就把路徑給壓縮了(把這條鏈上的所有點的前驅都變成總前驅),下一次再碰上原屬於這條鏈上的點時,尋找總前驅的過程會快很多。

示例**:

int

find

(int x)

return r;

}

另乙個優化(對「並」的優化):在join函式中,我們將一子圖的根節點作為另一子圖根節點的子點,而兩樹(子圖)的高度,也就是秩,不一樣,如果我們將秩大的樹合併到了另一圖之中,那麼下次find操作是就要多費幾步,所以,我們用啟發式的方式——比較兩樹的秩,將秩小的合併到秩大的之中。

不過這樣我們需要建立乙個rank陣列並全部初始化為0。

示例**:

void

join

(int p1,

int p2)

}

優化後的並查集示例**:

void

init

(int n)

intfind

(int x)

return r;

}void

join

(int p1,

int p2)

}

並查集及優化 C

include include include include using namespace std 查詢快,但是合併差 class unionfind1 int find int p bool isconnected int p,int q void union int p,int q 基於2的...

並查集的優化及應用

2018 05 01 15 13 08 並查集是乙個時空複雜度非常優越的資料結構,並且通過優化後其複雜度為。並查集的優化主要有兩個方面 路徑壓縮 按rank合併 public class unionfindset public int find int i public boolean union ...

並查集的實現與優化

並查集的實現與優化 班上有 n 名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 a 是 b 的朋友,b 是 c 的朋友,那麼我們可以認為 a 也是 c 的朋友。所謂的朋友圈,是指所有朋友的集合。給定乙個 n n 的矩陣 m,表示班級中學生之間的朋友關係。如果m i j 1,表...