到目前为止我所做的主要是基于Cormen等人的“算法导论”第571页。
我在python中有一个Node类,代表一个集合:
class Node:
def __init__(self, parent, rank = 0):
self.parent = parent
self.rank = rank
此实现将使用List
节点作为森林(我愿意更好地存储集合)。
Initialize()
返回一个节点列表,我将存储在变量set
中并传递给其他函数。
Find
在林中搜索值并返回它出现的集合。我选择使用for s in range(len(set)):
,这样在递归中我可以缩小由{传递的集合列表{1}}。
set[s:]
def Find(set, value):
for s in range(len(set)):
if value != set[s].parent:
set[s].parent = Find(set[s:], set[s].parent)
return set[s]
通过查找它们并推广排名较高的集合来合并林中的集合。
Merge
我在def Merge(set, value1, value2):
set_val_1 = Find(set, value1)
set_val_2 = Find(set, value2)
if set_val_1.rank > set_val_2.rank:
set_val_2.parent = set_val_1
else:
set_val_1.parent = set_val_2
if set_val_1.rank == set_val_2.rank:
set_val_2.rank += 1
和Find
时遇到了一些错误,即Merge
没有返回正确的设置,所以我不确定Find
工作正常。我希望得到一些帮助,以确保功能正确实施。
答案 0 :(得分:4)
您是否看过其他任何existing implementations?
答案 1 :(得分:2)
我没有这本书的最新版本,但这看起来并不像一个不相交的森林。
我认为你的错误是认为森林必须存储在一个集合中,你必须遍历这个集合才能在节点上进行操作。从set
和Merge()
移除Find()
并将Find()
实施为
def Find(n):
if n != n.parent:
n.parent = Find(n.parent)
return n.parent
就像在书中一样。然后添加一个MakeSet()
,它返回一个正确初始化的节点,也可能是一个SameSet()
函数:
def SameSet(n1, n2):
return Find(n1) == Find(n2)
您现在有一个工作的不相交集实现。
答案 2 :(得分:2)
假设每个节点都被初始化为它自己的父节点:
def Find(node):
while node is not node.parent:
node = node.parent
return node
答案 3 :(得分:1)
使用这个implementation作为起点,我创建了一个新的python类来处理不相交的集合,它也支持使用MongoDb的持久性。
在课堂上你应该能够:
UnionFind()
的实例,默认情况下使用python内置词典,稍后在MongoDb集合中决定consolidate()
您的结果您可能需要查看the code on github。
干杯, 西蒙
答案 4 :(得分:0)
维基百科page为不相交集数据结构上的基本operations提供了伪代码。这是Python的直接端口(采用路径压缩和按等级合并):
class Node:
"""Represents an element of a set."""
def __init__(self, id):
self.id = id
self.parent = self
self.rank = 0
self.size = 1
def __repr__(self):
return 'Node({!r})'.format(self.id)
def Find(x):
"""Returns the representative object of the set containing x."""
if x.parent is not x:
x.parent = Find(x.parent)
return x.parent
def Union(x, y):
"""Combines the sets x and y belong to."""
xroot = Find(x)
yroot = Find(y)
# x and y are already in the same set
if xroot is yroot:
return
# x and y are not in same set, so we merge them
if xroot.rank < yroot.rank:
xroot, yroot = yroot, xroot # swap xroot and yroot
# merge yroot into xroot
yroot.parent = xroot
xroot.size += yroot.size
if xroot.rank == yroot.rank:
xroot.rank = xroot.rank + 1
演示:
>>> a, b, c = map(Node, 'abc')
>>> Find(a), Find(b), Find(c)
(Node('a'), Node('b'), Node('c'))
>>> Find(a).size
1
>>> Union(a, b)
>>> Union(b, c)
>>> Find(a), Find(b), Find(c)
(Node('a'), Node('a'), Node('a'))
>>> Find(a).size
3