21.1不相交集合的操作
def:不相交集合数据结构维护了一个不相交动态集的集合S={S1, S2,...,Sk}。我们用一个代表来表示每个集合,他是这个集合的某个成员。设x表示一个动态集Sx的每个元素,我们希望支持以下三个操作:
使用不相交集合的数据结构来确定无向图的连通分量过程如下:
21.2 不相交集合的链表表示
用链表来表示集合实现如下:
class Set():
def __init__(self):
self.head = None
self.tail = None
self.size = 0
class Node():
def __init__(self, x):
self.set = None
self.value = x
self.next = None
def MAKE_SET(x):
node = Node(x)
st = Set()
st.head = node
st.tail = node
st.size = 1
node.set = st
return node
def FIND_SET(x):
return x.set.head
def UNION(x, y):
ySet = y.set
xSet = x.set
xTail = xSet.tail
yHead = ySet.head
ySet.head = None
ySet.tail = None
xTail.next = yHead
yHead.set = xSet
while yHead.next != None:
yHead = yHead.next
yHead.set = xSet
xSet.tail = yHead
return xSet.head
def WEIGHT_UNION(x, y):
xWeight = x.set.size
yWeight = y.set.size
if xWeight > yWeight:
ret = UNION(x, y)
ret.set.size = xWeight + yWeight
return ret
else:
ret = UNION(y, x)
ret.set.size = xWeight + yWeight
return ret
def PRINT(x):
head = x.set.head
while head != None:
print(head.value)
head = head.next
if __name__ == "__main__":
setf = MAKE_SET('f')
setg = MAKE_SET('g')
setd = MAKE_SET('d')
set1 = WEIGHT_UNION(setf, setg)
set1 = WEIGHT_UNION(set1, setd)
PRINT(set1)
print("=================")
setc = MAKE_SET('c')
seth = MAKE_SET('h')
sete = MAKE_SET('e')
setb = MAKE_SET('b')
set2 = WEIGHT_UNION(setc, seth)
set2 = WEIGHT_UNION(set2, sete)
set2 = WEIGHT_UNION(set2, setb)
PRINT(set2)
print("=================")
set3 = WEIGHT_UNION(set1, set2)
PRINT(set3)
print(setf.set.size)
以上过程示意图如下:
也可以采用加权的方式来合并提高合并效率:
21.3 不相交集合森林
不相交集合森林是不相交集合的更快实现:
class Node():
def __init__(self, x):
self.value = x
self.p = self
self.rank = 0
def MAKE_SET(x):
x.p = x
x.rank = 0
def UNION(x, y):
LINK(FIND_SET(x), FIND_SET(y))
def LINK(x, y):
if x.rank > y.rank:
y.p = x
else:
x.p = y
if x.rank == y.rank:
y.rank = y.rank + 1
def FIND_SET(x):
if x != x.p:
x.p = FIND_SET(x.p)
return x.p
def PRINT(x):
print(x.value)
if x.p != x:
PRINT(x.p)
if __name__ == "__main__":
array = []
array.append(Node('a'))
array.append(Node('b'))
array.append(Node('c'))
array.append(Node('d'))
array.append(Node('e'))
array.append(Node('f'))
for i in range(0, len(array)):
array[i].rank = i+1
for i in range(0, len(array)-1):
UNION(array[i], array[i+1])
PRINT(array[0])
print("-----------------")
FIND_SET(array[0])
for i in range(0, len(array)):
PRINT(array[i])
实现如下图所示结构:
并采用按秩合并和路径压缩两种启发式策略:
21.4 带路径压缩的按秩合并的分析