- Disjoint Set/Union-find Sets/并查集 的概念
https://algorithms.tutorialhorizon.com/disjoint-set-union-find-algorithm-union-by-rank-and-path-compression/
https://www.cnblogs.com/shadowwalker9/p/5999029.html
MakeSet/初始化树
The MakeSet operation makes a new set by creating a new element with a unique id, a rank of 0, and a parent pointer to itself. The parent pointer to itself indicates that the element is the representative member of its own set.
函数MakeSet 对所有元素创造全为0的rank矩阵,以及指向自己的parent矩阵。指向自己表明元素的代表是它们自己。
The MakeSet operation has O(1) time complexity.
函数MakeSet复杂度为O(1)
function MakeSet(x)
if x is not already present:
add x to the disjoint-set tree
x.parent := x
x.rank := 0
如果合并两个集合
最差情况复杂度O(LogN)
Pseudo Code:
function Union(x, y)
xRoot := Find(x)
yRoot := Find(y)
// x and y are already in the same set
if xRoot == yRoot
return
// x and y are not in same set, so we merge them
if xRoot.rank < yRoot.rank
xRoot.parent := yRoot
else if xRoot.rank > yRoot.rank
yRoot.parent := xRoot
else
xRoot.parent := yRoot
yRoot.rank := yRoot.rank + 1
路径压缩Path compression
function Find(x)
if x.parent != x
x.parent := Find(x.parent)
return x.parent
- kruskal
# Python program for Kruskal's algorithm to find
# Minimum Spanning Tree of a given connected,
# undirected and weighted graph
from collections import defaultdict
#Class to represent a graph
class Graph:
def __init__(self,vertices):
self.V= vertices #No. of vertices
self.graph = [] # default dictionary
# to store graph
# function to add an edge to graph
def addEdge(self,u,v,w):
self.graph.append([u,v,w]) #The append() method adds an item to the end of the list.
# A utility function to find set of an element i
# (uses path compression technique)
def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])
# A function that does union of two sets of x and y
# (uses union by rank)
def union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
# Attach smaller rank tree under root of
# high rank tree (Union by Rank)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
# If ranks are same, then make one as root
# and increment its rank by one
else :
parent[yroot] = xroot
rank[xroot] += 1
print ("if x != y而且xroot=",xroot,"yroot=",yroot,"rank相同, 把parent[y的parent] 替换为 x的parent,","rank是",rank,'\n')
# The main function to construct MST using Kruskal's
# algorithm
def KruskalMST(self):
result =[] #This will store the resultant MST
i = 0 # An index variable, used for sorted edges
e = 0 # An index variable, used for result[]
# Step 1: Sort all the edges in non-decreasing
# order of their
# weight. If we are not allowed to change the
# given graph, we can create a copy of graph
self.graph = sorted(self.graph,key=lambda item: item[2])
print ("self.graph是",self.graph,'\n')
parent = [] ; rank = []
# Create V subsets with single elements
# this is MakeSet(X)
for node in range(self.V):
parent.append(node) #parent is [0, 1, 2, 3]
rank.append(0) #rank is [0, 0, 0, 0]
# Number of edges to be taken is equal to V-1
while e < self.V -1 :
# Step 2: Pick the smallest edge and increment
# the index for next iteration
# for each e th, pick up one acceptable edge
u,v,w = self.graph[i]
# for each i th, pick up one possible edge
i = i + 1
x = self.find(parent, u)
y = self.find(parent ,v)
print ("当e=",e,"时","i=",i-1,"时",'\n')
print ("x是",x,'\n',"y是",y,'\n')
# If including this edge does't cause cycle,
# include it in result and increment the index
# of result for next edge
# 如果u的parent=v的parent,说明成环
if x != y:
e = e + 1
result.append([u,v,w])
self.union(parent, rank, x, y)
print ("if x != y,","parent是",parent,'\n')
# Else discard the edge
# print the contents of result[] to display the built MST
print ("Following are the edges in the constructed MST")
for u,v,weight in result:
#print str(u) + " -- " + str(v) + " == " + str(weight)
print ("%d -- %d == %d" % (u,v,weight))
# Driver code
g = Graph(4) #input sum. of vertices
g.addEdge(0, 1, 10) #input edges and weight
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.KruskalMST()
#This code is contributed by Neelam Yadav
Result:
self.graph是 [[2, 3, 4], [0, 3, 5], [0, 2, 6], [0, 1, 10], [1, 3, 15]]
当e= 0 时 i= 0 时
x是 2
y是 3
if x != y而且xroot= 2 yroot= 3 rank相同, 把parent[y的parent] 替换为 x的parent, rank是 [0, 0, 1, 0]
if x != y, parent是 [0, 1, 2, 2]
当e= 1 时 i= 1 时
x是 0
y是 2
if x != y, parent是 [2, 1, 2, 2]
当e= 2 时 i= 2 时
x是 2
y是 2
当e= 2 时 i= 3 时
x是 2
y是 1
if x != y, parent是 [2, 2, 2, 2]
Following are the edges in the constructed MST
2 – 3 == 4
0 – 3 == 5
0 – 1 == 10
分析:
当e= 0 时 i= 0 时, 加入edge[0], 选取no.2做root,parent[3]变成2
当e= 1 时 i= 1 时, 加入edge[1],parent[0]变成2
当e= 2 时 i= 2 时, 发现edge[2]的两个verticles 2 和0 的parent都是2,说明成环,丢弃
当e= 2 时 i= 3 时, 加入edge[3],parent[0]变成2