演算法筆記 並查集(union find演算法)

2021-10-04 12:48:03 字數 3033 閱讀 2170

對於一類問題,問題的輸入是一些物件兩兩之間的「相連關係」,並且這種「相連關係」是一種等價關係,即它具有以下性質:

那麼我們可以把相連的物件劃分為乙個等價類。問題的目標是根據輸入的所有相連關係,將物件空間劃分為多個等價類,並能夠判斷任意兩個物件是否屬於同乙個等價類。這個問題稱為動態連通性問題,動態連通性問題有以下現實場景的應用:

將問題抽象完成後,引入一些術語:將物件稱為觸點,將相連關係稱為連線,將等價類稱為連通分量或者簡稱分量。為了描述方便,直接0

00到n−1

n-1n−

1的整數表示n

nn個觸點。

將動態連通性問題的解決抽象為乙份api:

public

class

uf

實現時要注意以下要點:

為了實現上述功能,我們用乙個整數陣列id來記錄所有的物件所屬的分量。即id[p]表示的是物件p所屬的連通分量。那麼有以下實現

public

classuf}

public

intcount()

public

boolean

connected

(int p,

int q)

}

其中find()和union()兩個方法有不同的實現。

這種方法是要保證當且僅當id[p]等於id[p]時,p和q是屬於同乙個分量的。此時實現如下

public

intfind

(int p)

public

void

union

(int p,

int q)

} count--;}

}

分析:

這種方法不需要保證同乙個分量中的觸點的id值相同,id值只是同乙個分量中另乙個觸點(或者也可以是觸點自身),此時每乙個分量中必定有乙個觸點的id值是指向自身的,這個觸點就可以被認為是該分量的「根觸點」,用以代表整個分量。

public

intfind

(int p,

int q)

public

void

union

(int p,

int q)

}

這種方法其實是用一棵樹來表示乙個分量,整個id陣列用父連線的形式表現了一片森林。

分析:為了防止最壞情況的出現,需要對quick-union演算法進行優化,在quick-union演算法中,union()操作是隨意的將一棵樹連線到另一棵樹,改進的方法就是記錄每一棵樹的大小並總是將較小的樹連線到較大的樹上。這種方法稱為加權quick-union演算法。這項改動需要新增乙個陣列和一些**來記錄樹中的節點樹。實現如下:

public

class

weightedquickunionuf

public

intcount()

public

boolean

connected

(int p,

int q)

public

intfind

(int p)

public

void

union

(int p,

int q)

else

count--;}

}

分析:

(leetcode. 547)班上有 n 名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 a 是 b 的朋友,b 是 c 的朋友,那麼我們可以認為 a 也是 c 的朋友。所謂的朋友圈,是指所有朋友的集合。

給定乙個 n * n 的矩陣 m,表示班級中學生之間的朋友關係。如果m[i][j] = 1,表示已知第 i 個和 j 個學生互為朋友關係,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。

示例1:

輸入:

[[1,1,0],

[1,1,0],

[0,0,1]]

輸出: 2

說明:已知學生0和學生1互為朋友,他們在乙個朋友圈。

第2個學生自己在乙個朋友圈。所以返回2。

示例2:

輸入:

[[1,1,0],

[1,1,1],

[0,1,1]]

輸出: 1

說明:已知學生0和學生1互為朋友,學生1和學生2互為朋友,所以學生0和學生2也是朋友,所以他們三個在乙個朋友圈,返回1。

注意:n 在[1,200]的範圍內。

對於所有學生,有m[i][i] = 1。

如果有m[i][j] = 1,則有m[j][i] = 1。

題解:

class

solution}}

return uf.

count()

;}class

ufpublic

intcount()

public

intfind

(int p)

public

void

union

(int p,

int q)

else

count--;}

}}

演算法筆記 並查集

專題 並查集 一 引入 在一些有n個元素的集合應用問題中,我們通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪哪個集合中。該問題看似並不複雜,但資料量極大,若用正常的資料結構來描述的話,往往超過了空間的限制,計算機無法承受 而且...

並查集演算法筆記

並查集是一種用來管理元素分組情況的資料結構,並查集可以高效的進行如下操作 使用樹狀結構來實現 在樹形資料結構中,如果發生了退化的情況,複雜度就會變得很高。在並查集中,可以按照如下方法避免退化 並查集複雜度平均下來每次查詢和合併的複雜度都是常數的 阿克曼函式 leetcode 547.friend c...

演算法筆記 並查集

先給出源 和輸入輸出測試結果 includeusing namespace std const int n 110 int father n 存放父親節點 bool isboot n 標記時否為根節點 int findfather int x return x void union int a,in...