樹型資料結構 並查集的簡介與使用!

2021-10-16 02:07:07 字數 3060 閱讀 5925

示例**:冗餘連線

並查集,在一些有n個元素的集合應用問題中,我們通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪個集合中。這一類問題近幾年來反覆出現在資訊學的國際國內賽題中,其特點是看似並不複雜,但資料量極大,若用正常的資料結構來描述的話,往往在空間上過大,計算機無法承受;即使在空間上勉強通過,執行的時間複雜度也極高,根本就不可能在比賽規定的執行時間(1~3秒)內計算出試題需要的結果,只能用並查集來描述。

**並查集是一種樹型的資料結構,**用於處理一些不相交集合(disjoint sets)的合併及查詢問題。常常在使用中以森林來表示。

把每個點所在集合初始化為其自身。

通常來說,這個步驟在每次使用該資料結構時只需要執行一次,無論何種實現方式,時間複雜度均為o(n)。

// 注:因為節點是從1開始計數的,因此長度需要增加一位

int[

] parent =

newint

[n+1];

for(

int i =

1; i <= n; i++

)

查詢元素所在的集合,即根節點。

通俗地講乙個故事:幾個家族進行宴會,但是家族普遍長壽,所以人數眾多。由於長時間的分離以及年齡的增長,這些人逐漸忘掉了自己的親人,只記得自己的爸爸是誰了,而最長者(稱為「祖先」)的父親已經去世,他只知道自己是祖先。為了確定自己是哪個家族,他們想出了乙個辦法,只要問自己的爸爸是不是祖先,一層一層的向上問,直到問到祖先。如果要判斷兩人是否在同一家族,只要看兩人的祖先是不是同一人就可以了。

// 並查集方法:查詢每乙個節點的父節點

public

intfind

(int

parent,

int index)

return parent[index]

;//返回節點的根節點

}

將兩個元素所在的集合合併為乙個集合。

通常來說,合併之前,應先判斷兩個元素是否屬於同一集合,這可用上面的「查詢」操作實現。

宴會上,乙個家族的祖先突然對另乙個家族說:**我們兩個家族交情這麼好,不如合成一家好了。**另乙個家族也欣然接受了。我們之前說過,並不在意祖先究竟是誰,所以只要其中乙個祖先變成另乙個祖先的兒子就可以了。

public

boolean

union

(int

parent,

int i,

int j)

// 加入並查集

parent[

find

(parent, i)]=

find

(parent, j)

;return

true;}

public

void

union

(int

parent,

int index1,

int index2)

在本問題中, 樹指的是乙個連通且無環的無向圖。

輸入乙個圖,該圖由乙個有著n個節點 (節點值不重複1, 2, …, n) 的樹及一條附加的邊構成。附加的邊的兩個頂點包含在1到n中間,這條附加的邊不屬於樹中已存在的邊。

結果圖是乙個以邊組成的二維陣列。每乙個邊的元素是一對[u, v] ,滿足 u < v,表示連線頂點u 和v的無向圖的邊。

返回一條可以刪去的邊,使得結果圖是乙個有著n個節點的樹。如果有多個答案,則返回二維陣列中最後出現的邊。答案邊 [u, v] 應滿足相同的格式 u < v。

示例 1:

輸入: [[1,2], [1,3], [2,3]]

輸出: [2,3]

解釋: 給定的無向圖為:

示例 2:

輸入: [[1,2], [2,3], [3,4], [1,4], [1,5]]

輸出: [1,4]

解釋: 給定的無向圖為:

在一棵樹中,邊的數量比節點的數量少 11。如果一棵樹有 nn 個節點,則這棵樹有 n-1n−1 條邊。這道題中的圖在樹的基礎上多了一條附加的邊,因此邊的數量也是 nn。

樹是乙個連通且無環的無向圖,在樹中多了一條附加的邊之後就會出現環,因此附加的邊即為導致環出現的邊。

可以通過並查集尋找附加的邊。初始時,每個節點都屬於不同的連通分量。遍歷每一條邊,判斷這條邊連線的兩個頂點是否屬於相同的連通分量。

如果兩個頂點屬於不同的連通分量,則說明在遍歷到當前的邊之前,這兩個頂點之間不連通,因此當前的邊不會導致環出現,合併這兩個頂點的連通分量。

如果兩個頂點屬於相同的連通分量,則說明在遍歷到當前的邊之前,這兩個頂點之間已經連通,因此當前的邊導致環出現,為附加的邊,將當前的邊作為答案返回。

class

solution

​ for

(int i =

0; i < nodescount; i++

)else

​ }

​ return

newint[0

];}//合併,其中乙個節點的根節點成為另乙個節點的根節點的孩子

public

void

union

(int

parent,

int index1,

int index2)

//查詢根節點

public

intfind

(int

parent,

int index)

​ return parent[index];}

}

整體的思路比較固定,**模板可以熟記!

《資料結構》並查集與樹

查 給定乙個元素,查詢它在哪個集合內 並 合併兩個元素所在的集合 元素 結點 集合 樹 多個集合 森林 用樹的根節點作為不同樹的標誌 合併時只需要將根節點鏈結 用陣列表示樹,陣列下標表示元素值,陣列的值表示該元素對應的父親結點 father i j 元素i的父親結點是j 對於根節點 father i...

資料結構之樹(並查集)

0,2,4,6,8的標籤為0。1,3,5,7,9的標籤為1。標籤為0和1表示兩個不同的集合。查詢元素p所對應的集合編號,o 1 複雜度 private intfind int p 檢視元素p和元素q是否所屬乙個集合,o 1 複雜度 public boolean isconnected int p,i...

資料結構簡記 樹與森林 並查集

並查集 union find sets typedef struct ptnode ptnode typedef struct ptree 樹的雙親儲存結構型別typedef struct childnode childnode 孩子在鍊錶中結點型別 typedef struct pctreenod...