Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python OOP不相交集性能_Python_Algorithm_Performance_Kruskals Algorithm_Disjoint Sets - Fatal编程技术网

Python OOP不相交集性能

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

我构建了一个不相交的集合数据结构,用于Kruskal的MST算法。我需要加载一个带有200k个互连节点的图,然后将其合并,我认为我的数据结构实现是一个瓶颈

您对如何提高绩效有何建议?我认为我的查找方法可能有问题

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)