什麼是並查集?
這裏借用百度百科的一句話:並查集是一種樹型的數據結構,用於處理一些不相交集合(disjoint sets)的合併及查詢問題。常常在使用中以森林來表示。假設現在有一個武林大會,包含了少林、峨嵋、武當等門派,通過並查集就可以將每個人歸類到自己的門派中。
代碼實現
class UnionFind:
def __init__(self):
self.co = 0 # 用於記錄羣的個數
self.parent = [] # 索引是每個節點本身,值是每個節點的父節點
self.size = [] # 用於記錄每個羣的節點數目
#
def find(self, x):
while self.parent[x] != x:
# self.parent[x] = self.parent[self.parent[x]] # 用於路徑壓縮
x = self.parent[x]
return x
def union(self, p, q):
rootP = self.find(p)
rootQ = self.find(q)
if rootP == rootQ:
return
# 下面的這個if語句用將節點數少的合併到節點數多的羣中
if self.size[rootP] > self.size[rootQ]:
self.parent[rootQ] = rootP
self.size[rootP] += self.size[rootQ]
else:
self.parent[rootP] = rootQ
self.size[rootQ] += self.size[rootP]
self.co -= 1
# 用於判斷p和q之間是否連通,如果兩個節點的父節點是相同的,那麼就是連通的
def connected(self, p, q):
rootP = self.find(p)
rootQ = self.find(q)
return rootP == rootQ
# 返回有多少個羣
def count(self):
return self.co
# 初始化,節點的父節點就是其本身,假設n=10,那麼就有10個羣,self.parent=[0,1,2,3,4,5,6,7,8,9],self.parent[0]=0表示0節點的父節點是0。每個羣的size,也就是包含的節點數目就是1,self.size[0]=1。
def uf(self, n):
self.co = n
self.parent = [0 for _ in range(n)]
self.size = [0 for _ in range(n)]
for i in range(n):
self.parent[i] = i
self.size[i] = 1
unionF = UnionFind()
unionF.uf(10)
print("初始化每個節點的父節點:", unionF.parent)
print("初始化的羣個數:", unionF.count())
unionF.union(0, 3) # 0,3建立關係
unionF.union(3, 7) # 3,7建立關係
unionF.union(7, 9) # 7,9建立關係
unionF.union(2, 8) # 2,8建立關係
print("判斷{}與{}之間是否在一個羣裏面:{}".format(3, 8, unionF.connected(3, 8)))
print("返回節點{}的父節點{}".format(7, unionF.find(7)))
print("當前每個節點的父節點:", unionF.parent)
print("當前羣的個數:", unionF.count())
print("當前每一個羣的節點個數:", unionF.size)
結果:
初始化每個節點的父節點: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
初始化的羣個數: 10
判斷3與8之間是否在一個羣裏面:False
返回節點7的父節點3
當前每個節點的父節點: [3, 1, 8, 3, 4, 5, 6, 3, 8, 3]
當前羣的個數: 6
當前每一個羣的節點個數: [1, 1, 1, 4, 1, 1, 1, 1, 2, 1]
更具體的介紹可以去參考labuladong的算法小抄。