算法与数据结构——并查集

C++实现及理论https://www.cnblogs.com/polly333/category/720001.html

https://github.com/liuyubobobo/Play-with-Algorithms

python实现https://github.com/ShiveryMoon/Imooc-Algorithm-PythonEdition


经过路径压缩后,时间复杂度近乎为O(1)

并查集——查

    def find(self,p):#查
        if p>=0 and p<self.count:
            while p != self.parent[p]:
                self.parent[p]=self.parent[self.parent[p]]#这一行代码修改了树结构
                p=self.parent[p]
            return p
            #if p != self.parent[p]:  传说中那更精彩的回答
                #self.parent[p]=self.find(self.parent[p])
            #return parent[p]
        else:
            raise KeyError('Key not in parent')

并查集——并(优化:避免并查集过长)

    def Union(self,p,q):#并
        pRoot,qRoot=self.find(p),self.find(q)#找到p,q指向的根
        if pRoot==qRoot:
            return
        #避免并集树过长,基于rank优化,rank[i]表示根节点为i的树的高度
        if self.rank[pRoot]<self.rank[qRoot]:
            self.parent[pRoot]=qRoot
        elif self.rank[pRoot]>self.rank[qRoot]:
            self.parent[qRoot]=pRoot
        else:
            self.parent[pRoot]=qRoot
            self.rank[qRoot]+=1
        #基于size优化,size指本身节点+所有子节点数量
        if self.size[pRoot]<self.size[qRoot]:
            self.parent[pRoot] = qRoot
            self.size[qRoot]+=self.size[pRoot]
        else:
            self.parent[qRoot]=pRoot;
            self.size[pRoot]+=self.size[qRoot]

路径压缩(父节点的父节点)

节点4、节点2路径压缩


通过递归压缩路径


            while p != self.parent[p]:
                self.parent[p]=self.parent[self.parent[p]]#路径压缩优化,这一行代码修改了树结构
                p=self.parent[p]
            return p
            #if p != self.parent[p]:  传说中那更精彩的回答,递归到最终根节点,路径压缩
                #self.parent[p]=self.find(self.parent[p])
            #return parent[p]
完整代码
# -*- coding: utf-8 -*-

class UnionFind(object):
    def __init__(self,count=10):
        self.count=count
        self.rank=[1 for x in range(count)]
        self.parent=[x for x in range(count)]
        self.size =[1 for x in range(count)]
        #初始化时所有元素都不互连

    def find(self,p):
        if p>=0 and p<self.count:
            while p != self.parent[p]:
                self.parent[p]=self.parent[self.parent[p]]#路径压缩优化,这一行代码修改了树结构
                p=self.parent[p]
            return p
            #if p != self.parent[p]:  传说中那更精彩的回答,递归到最终根节点,路径压缩
                #self.parent[p]=self.find(self.parent[p])
            #return parent[p]
        else:
            raise KeyError('Key not in parent')

    def isConnected(self,p,q):
        return self.find(p) == self.find(q)

    def Union(self,p,q):
        pRoot,qRoot=self.find(p),self.find(q)#找到p,q指向的根
        if pRoot==qRoot:
            return
        #避免并集树过长
        #基于rank优化,rank[i]表示根节点为i的树的高度
        if self.rank[pRoot]<self.rank[qRoot]:
            self.parent[pRoot]=qRoot
        elif self.rank[pRoot]>self.rank[qRoot]:
            self.parent[qRoot]=pRoot
        else:
            self.parent[pRoot]=qRoot
            self.rank[qRoot]+=1
        #基于size优化,size指本身节点+所有子节点数量
        if self.size[pRoot]<self.size[qRoot]:
            self.parent[pRoot] = qRoot
            self.size[qRoot]+=self.size[pRoot]
        else:
            self.parent[qRoot]=pRoot;
            self.size[pRoot]+=self.size[qRoot]
uf=UnionFind(10)
uf.Union(1,2)
uf.Union(1,3)
uf.Union(4,5)
uf.Union(4,6)
uf.Union(3,6)
print(uf.isConnected(3,5))
print(uf.size)
print(uf.rank)
'''
0         1          7   8   9
      /   |   \
     2    3    4
              / \
             5   6
'''

猜你喜欢

转载自blog.csdn.net/u012084802/article/details/80416411