路徑壓縮 並查集路徑壓縮

2021-10-13 01:27:13 字數 2259 閱讀 9088

如何描述乙個複雜的連線關係?如圖,很容易判斷緊鄰的2個人關係,但中間的連線很多很亂,怎麼判斷出兩個人的關係呢?

並查集就是一種結構,通過儲存節點以及節點上的標籤,來判斷這兩個節點是否連線在一起。當兩個節點繫結時,可以任選其中乙個節點的標籤,指定另乙個節點。當判斷兩個節點是不是連線時,可以上溯節點的祖宗節點,如果祖宗節點相同,那麼節點相連。此時,節點上的標籤可理解為指向父親節點。

並查集的並&查

1.節點列表

並查集中的節點只需要儲存父親節點的資訊,那麼線性結構字典、列表都可以。我們用一維陣列,索引是自身id,值指向父親。

初始化時每個節點指向自身。

class unionfind:

def __init__(self,size):

self.size = size

self.parent = np.arange(size)

def union(self,p,q): ##將兩個節點連線在一起

def isconnected(self,p,q): ## 判斷兩個節點是否相連

2.判斷兩個節點相連

當兩個節點的祖宗節點相同時,兩個節點就是連線節點。

def find(self,p):

assert p>=0 and p

while (self.parent[p]!=p):

##向上遍歷,當父節點不是自己時,

##那麼還存在父節點,繼續遍歷。

p = self.parent[p]

return p

def isconnected(self,p,q):

##當祖宗節點相同時,兩個節點是連線節點

return self.find(p)==self.find(q)

3.節點連線

當節點連線時,需要將2個節點的祖宗節點相連,可任選乙個節點連線另乙個節點。

def union(self,p,q):

proot = self.find(p)

qroot = self.find(q)

if proot == qroot:

return

else:

## 第乙個節點祖宗節點指向第二節點的祖宗節點

self.parent[proot] = qroot

4.優化連線

第3小節,我們任意選擇乙個節點連線,這樣的選擇有問題。舉例:一層和二層節點集合合併:

如果二層節點的祖宗節點連線到一層節點上,那麼就形成了乙個三層節點集。

另一種可能,一層節點連線到二層祖宗節點,新集還是二層。

層數越少,查詢祖宗節點的代價越小,應讓節點層數少的連線到層數高的。

class unionfind:

def __init__(self,size):

self.size = size

self.parent = np.arange(size)

self.rank = np.ones(size) //記錄該節點下面的層次,預設都是1層

def unionbyrank(self,p,q):

assert p>=0 and p=0 and q

proot = self.find(p)

qroot = self.find(q)

if proot == qroot:

return self

else:

## rank小的,新增到rank大的,這樣的合併不增加rank。rank節點向上遍歷的步數。

if(self.rank[proot] > self.rank[qroot]):

self.parent[qroot] = proot

elif(self.rank[qroot] > self.rank[proot]):

self.parent[proot] = qroot

else:

self.parent[proot] = qroot

self.rank[qroot] +=1

return self

5.路徑壓縮

進一步優化,使每個節點直接指向它的祖宗節點。

def findcompress2(self,p):

if p!=self.parent(p):

self.parent[p] = self.findcompress2(self.parent[p])

return self.parent[p]

通過遞迴呼叫,函式從某一點出發,上溯到祖宗節點,返回值傳遞祖宗節點。函式返回時,相當於祖宗節點向下遍歷,對每乙個節點父節點重新賦值。

總結:

並查集 壓縮路徑

並查集 union findsets 一種簡單的用途廣泛的集合.並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多,如其求無向圖的連通分量個數等。最完美的應用當屬 實現kruskar演算法求最小生成樹。並查集的精髓 即它的三種操作,結合實現 模板進行理解 1 make s...

並查集路徑壓縮

使用並查集查詢時,如果查詢次數很多,那麼使用樸素版的查詢方式肯定要超時。比如,有一百萬個元素,每次都從第一百萬個開始找,這樣一次運算就是10 6,如果程式要求查詢個一千萬次,這樣下來就是10 13,肯定要出問題的。這是樸素查詢的 適合資料量不大的情況 int findx int x 下面是採用路徑壓...

並查集壓縮路徑

並查集壓縮路徑 先找到所有節點的最終的根節點,然後通過將所有不與根節點直接相連的並且父節點是根節點的節點直接接在根節點上面,從而減少查詢時間,來達到時間節省的目的!關於並查集尋找父節點的演算法 主要分為兩類 一 通過遞迴求解。優點 較短,並且遞迴的過程中已經包含了壓縮路徑。缺點 資料較大的時候,容易...