1. 程式人生 > >c++ 並查集

c++ 並查集

POWERED BY PHANTOM_LSH
大神勿噴。

在程式設計和演算法設計的時候,我們經常會遇到一些儲存集合的情況,例如使用Kruskal演算法求最小生成樹的時候。我們只關心一些元素是否在一個集合裡而不關心它的順序(如Kruskal演算法中的邊),我們可以使用一種新的資料結構——並查集。
我們對一些在同一集合的元素取其中一個作為代表元素(通常是遞迴中第一次遇到的),以它為樹根建立一棵樹,假設陣列p記錄節點的父結點,可以在拓展的時候直接拓展樹。為了比較兩個元素是否在同一個集合中,我們只要遞迴找到兩個元素的代表元素,如果相同則在同意集合中。

一個並查集樹的圖示這裡寫圖片描述

【路徑優化】如圖所示,我們發現,以A為代表元素的一個集合,如果要查B結點需要沿綠色線遞迴,再查C結點又要同樣的遞迴,有大量的重複運算,效率低下。所以,我們可以把沿途查到的結點的父結點直接修改為代表元素,讓下一次查詢更快,這就是並查集的路徑優化。
 總的來說,並查集的查詢程式碼可以寫的極簡(劉汝佳風格),用p陣列記錄集合樹結點的父結點編號,則這個函式返回代表元素編號:
int findnode(int x){return p[x]==x ? x : p[x] = findnode(p[x]);}

解釋:其中規定代表元素的父結點是自己。?:是if語句的表示式形式,利用c++裡面賦值語句有返回值(就是賦的值)的性質進行路徑優化同時返回。
這一行程式碼太經典,希望大家記住。

“`