如果g或{}的元素很大,可以使用不相交集来提高效率。在
这个数据结构可以用来将每个元素分类到它应该属于的集合中。在
第一步是用所有g集合的索引在g中标记它们,构建一个不相交的集合:g=[[], [], [0, 2], [1, 5], [0, 2, 3, 7], [4, 6], [1, 4, 5, 6], [], [], [3, 7],[99]]
g = map(set, g)
dss = CDisjointSets()
for i in xrange(len(g)):
dss.MakeSet(i)
然后,只要交集不为空,集合就被合并:
^{pr2}$
此时,dss为应该连接在一起的g集提供了一个通用标签:print(dss)parent(0) = 0
parent(1) = 1
parent(2) = 2
parent(3) = 3
parent(4) = 2
parent(5) = 3
parent(6) = 3
parent(7) = 7
parent(8) = 8
parent(9) = 2
parent(10) = 10
现在您只需构建新的集合,将具有相同标签的集合连接起来:l2set = dict()
for i in xrange(len(g)):
label = dss.FindLabel(i).getLabel()
l2set[label] = l2set.get(label, set()).union(g[i])
print(l2set)
导致:{0: set([]), 1: set([]), 2: set([0, 2, 3, 7]), 3: set([1, 4, 5, 6]), 7: set([]), 8: set([]), 10: set([99])}
这是我使用的不相交集的实现,但您肯定可以找到另一个具有更好sintax的方法:""" Disjoint Sets
-
Pablo Francisco Pérez Hidalgo
December,2012. """
class CDisjointSets:
#Class to represent each set
class DSet:
def __init__(self, label_value):
self.__label = label_value
self.rank = 1
self.parent = self
def getLabel(self):
return self.__label
#CDisjointSets Private attributes
__sets = None
#CDisjointSets Constructors and public methods.
def __init__(self):
self.__sets = {}
def MakeSet(self, label):
if label in self.__sets: #This check slows the operation a lot,
return False #it should be removed if it is sure that
#two sets with the same label are not goind
#to be created.
self.__sets[label] = self.DSet(label)
#Pre: 'labelA' and 'labelB' are labels or existing disjoint sets.
def Join(self, labelA, labelB):
a = self.__sets[labelA]
b = self.__sets[labelB]
pa = self.Find(a)
pb = self.Find(b)
if pa == pb:
return #They are already joined
parent = pa
child = pb
if pa.rank < pb.rank:
parent = pb
child = pa
child.parent = parent
parent.rank = max(parent.rank, child.rank+1)
def Find(self,x):
if x == x.parent:
return x
x.parent = self.Find(x.parent)
return x.parent
def FindLabel(self, label):
return self.Find(self.__sets[label])
def __str__(self):
ret = ""
for e in self.__sets:
ret = ret + "parent("+self.__sets[e].getLabel().__str__()+") = "+self.FindLabel(e).parent.getLabel().__str__() + "\n"
return ret