並查集路徑壓縮 並查集 UnionFind 入門

2021-10-12 04:39:40 字數 1444 閱讀 1561

咳咳,剛看完海賊更新,馬上呼哧呼哧寫下這篇文章,這週的目標就是出一篇並查集相關的文章,真的是時間咻咻一下就沒了。     

本文閱讀大概需要3分鐘。      好了,並查集呢,英文叫union-find , 並查集是一種樹型的資料結構,通常來用於處理一些不相交集合的合併(union)問題,以及查詢(find)問題。      如下:       1 : 有兩個區域 area 1 和 area 2       2 :  每個區域裡面,每個子節點只可以給父節點打**,根節點給自己打**. 例如area1中,d可以打給b,b可以打給a,a可以打給自己 (a:我就是要自己打自己 ^-^ )       那麼問題來了,如果d要給e通訊,要經過多少步呢?        

既然只能打給父節點,那麼d需要先找到根節點a, 然後由a傳送給e。所以可以先宣告乙個 find 函式來查詢根節點,結束條件為:當節點nodea的父節點是本身的時候,那麼這個節點就是根節點root:

int maxnum = ...;// 儲存每個節點的父節點,例如 nodea 的父節點就是pre[nodea]node pre[maxnum];// find 函式,查詢根節點// 遞迴版本private node find(node node)// 迴圈版本private node find(node node)
find 函式比較簡單,當然一般還會伴隨有路徑壓縮 。舉個栗子,當你的手機非常多的時候,樹的深度就會非常深,那麼查詢耗時會比較大。路徑壓縮指的是:讓每個子節點的父節點都直接是根節點, 如下:       

我們稍微修改下find函式達到路徑壓縮的效果:

private node find(node node)   return root; // 返回根節點}
既然可以找到根節點了,那麼根節點a要給e通訊就簡單了,那就是合併(union)了 :
// a:根節點a  e:根節點 eprivate void join(node a,node e)
對的,就是這麼一步,將 area1 和 area2 連線起來,所以d就可以和e通訊了。換一下另乙個場景,村莊a裡面的某一戶要到村莊b,那麼這一戶到村莊a的村頭之後,只需要再修一條路到b,就可以到b了。      回到上面的問題,a到e通訊需要多少步呢? 如果每到乙個節點算一步,那麼就是查詢以及合併的步數加起來就是啦,這裡就不給出**了。     並查集操作作為比較常見的演算法,在geeksforgeeks上也挺多相關的問題,例如島嶼問題字串轉換等,更多可以在這裡學習鞏固下:
當然在leetcode上也是挺多的,搜尋對應的tag就能找到,好了水文到此結束,很簡單的一篇文章,over .  週末愉快。

並查集 壓縮路徑

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

並查集路徑壓縮

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

並查集壓縮路徑

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