Python OOP不相交集性能
我构建了一个不相交的集合数据结构,用于Kruskal的MST算法。我需要加载一个带有200k个互连节点的图,然后将其合并,我认为我的数据结构实现是一个瓶颈 您对如何提高绩效有何建议?我认为我的查找方法可能有问题Python OOP不相交集性能,python,algorithm,performance,kruskals-algorithm,disjoint-sets,Python,Algorithm,Performance,Kruskals Algorithm,Disjoint Sets,我构建了一个不相交的集合数据结构,用于Kruskal的MST算法。我需要加载一个带有200k个互连节点的图,然后将其合并,我认为我的数据结构实现是一个瓶颈 您对如何提高绩效有何建议?我认为我的查找方法可能有问题 class partition(object): def __init__(self, element=None): self.size = 0 if element == None: self.contents = set
class partition(object):
def __init__(self, element=None):
self.size = 0
if element == None:
self.contents = set()
self.representative = None
else:
self.contents = {element}
self.representative = element
self.size = 1
def find(self, element):
return element in self.contents
def add(self, partition):
self.contents = self.contents.union(partition)
self.size = len(self.contents)
def show(self):
return self.contents
def __repr__(self):
return str(self.contents)
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.forest = {}
def make_set(self, element):
if self.find(element) == False:
new_partition = partition(element)
self.forest[new_partition.representative] = new_partition
self.partitions_count += 1
def union(self, x, y):
if x != y:
if self.forest[x].size < self.forest[y].size:
self.forest[y].add(self.forest[x].show())
self.delete(x)
else:
self.forest[x].add(self.forest[y].show())
self.delete(y)
def find(self, element):
for partition in self.forest.keys():
if self.forest[partition].find(element):
return self.forest[partition].representative
return False
def delete(self, partition):
del self.forest[partition]
self.partitions_count -= 1
if __name__ == '__main__':
t = disjoint_set()
t.make_set(1)
t.make_set(2)
t.make_set(3)
print("Create 3 singleton partitions:")
print(t.partitions_count)
print(t.forest)
print("Union two into a single partition:")
t.union(1,2)
print(t.forest)
print(t.partitions_count)
类分区(对象):
定义初始化(自,元素=无):
self.size=0
如果元素==无:
self.contents=set()
self.representative=无
其他:
self.contents={element}
自我代表=元素
self.size=1
def查找(自我,元素):
返回self.contents中的元素
def添加(自身,分区):
self.contents=self.contents.union(分区)
self.size=len(self.contents)
def显示(自我):
返回自己的内容
定义报告(自我):
返回str(self.contents)
类不相交集合(对象):
定义初始化(自):
self.u计数=0
self.forest={}
def make_设置(自身、元件):
如果self.find(元素)=False:
新分区=分区(元素)
self.forest[new_partition.representative]=新的_分区
self.u计数+=1
def接头(自、x、y):
如果x!=y:
如果self.forest[x]。大小
编辑:
在阅读了评论并做了额外的研究之后,我意识到我原来的算法设计得多么糟糕。我从头开始,把这一切都放在一起。我将所有分区放在一个哈希表中,并在find()中使用路径压缩。这看起来怎么样?有什么突出的问题需要我解决吗
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.size = {}
self.parent = {}
def make_set(self, element):
if self.find(element) == False:
self.parent[element] = element
self.size[element] = 1
self.partitions_count += 1
def union(self, x, y):
xParent = self.find(x)
yParent = self.find(y)
if xParent != yParent:
if self.size[xParent] < self.size[yParent]:
self.parent[xParent] = yParent
self.size[yParent] += self.size[xParent]
self.partitions_count -= 1
else:
self.parent[yParent] = xParent
self.size[xParent] += self.size[yParent]
self.partitions_count -= 1
def find(self, element):
if element in self.parent:
if element == self.parent[element]:
return element
root = self.parent[element]
while self.parent[root] != root:
root = self.find(self.parent[root])
self.parent[element] = root
return root
return False
if __name__ == '__main__':
t = disjoint_set()
t.make_set(1)
t.make_set(2)
t.make_set(3)
t.make_set(4)
t.make_set(5)
print("Create 5 singleton partitions")
print(t.partitions_count)
print("Union two singletons into a single partition")
t.union(1,2)
print("Union three singletones into a single partition")
t.union(3,4)
t.union(5,4)
print("Union a single partition")
t.union(2,4)
print("Parent List: %s" % t.parent)
print("Partition Count: %s" % t.partitions_count)
print("Parent of element 2: %s" % t.find(2))
print("Parent List: %s" % t.parent)
类不相交集合(对象):
定义初始化(自):
self.u计数=0
self.size={}
self.parent={}
def make_设置(自身、元件):
如果self.find(元素)=False:
self.parent[元素]=元素
自身大小[元素]=1
self.u计数+=1
def接头(自、x、y):
xParent=self.find(x)
yParent=self.find(y)
如果xParent不是家长:
如果self.size[xParent]
我猜您的find实现没有有效地运行,应该是这样的
以下更改可能会有所帮助
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.forest = {}
self.parent = {}
def make_set(self, element):
if not self.find(element):
new_partition = partition(element)
self.parent[element] = element
self.forest[new_partition.representative] = new_partition
self.partitions_count += 1
def union(self, x, y):
if x != y:
if self.forest[x].size < self.forest[y].size:
self.forest[y].add(self.forest[x].show())
#Update parent details
self.parent[self.forest[x].representative] = self.forest[y].representative
self.delete(x)
else:
self.forest[x].add(self.forest[y].show())
#Update parent details
self.parent[self.forest[y].representative] = self.forest[x].representative
self.delete(y)
def find(self, element):
if self.parent[element] == element:
return element
else:
return find(element)
尝试使用set的更新方法(这是一个就地并集)。我认为这会导致大量节点的内存开销。差不多
self.contents.update(partition)
关于集合并集和更新函数有一个很好的讨论
希望有帮助 你能添加一个if name==“main”部分来显示用法吗?是的,很抱歉!现在添加。您刚刚选择了几个听起来有点像不相交集林的名称,然后编写了一个与真正不相交集林无关的非常简单的算法。试试树数据结构?这根本不是路径压缩。这个算法本质上与不相交的集合林或路径压缩无关。所谓路径压缩,我指的是保持find的执行在O(1)中。同意你所说的-这不是一个路径压缩实现。路径压缩的目的是将操作保持在O(1)正确吗?这是我想传达的一些信息。删除了对路径压缩的提及。感谢您指出它。它也不是O(1),路径压缩也不会使查找在O(1)中运行。这里的
partition.find
方法是O(1),但这不是标准的不相交集操作;实际的不相交集查找操作是通过disjoint\u set.find
实现的,我们必须实际查找元素所属的集合。那是O(len(self.forest)),这太可怕了。不相交的_set.find的实现中存在缺陷。我做了一些改变@用户2357112检查这是否可以改进或存在任何其他缺陷。感谢@ArunKumar的评论。我将尝试这些更改。
self.contents.update(partition)