并查集的python实现

依然范特西╮ 提交于 2020-02-22 15:50:08
import numpy as np
import os


class DIS_JOIN(object):
    def __init__(self):
        '''
        并查集算法
        拥有两个函数
        一个是把某个元素放在某个集合中
        另一个是返回一个list,包含所有集合和集合中所有的点
        '''
        self.Set = None
        self.Sum = None
        self.n = None

    def clear(self, n):
        '''
        初始化
        n为一共有多少个元素
        '''
        self.Set = np.zeros(n, dtype=int)
        self.Set = self.Set - 1     # 都初始化为-1. 表示他自己就是根.   Set是一个数组.
        # Set[i] 表示i的根是谁.
        self.Sum = n
        self.n = n
        return

    def find_r(self, p):
        '''
        返回p属于那一个集合
        '''
        if self.Set[p] < 0:
            return p

        self.Set[p] = self.find_r(self.Set[p])  #通过迭代不停的找根.
        return self.Set[p]

    def join(self, a, b):
        '''
        将元素b加入元素a所在的集合中
        '''
        ra = self.find_r(a)
        rb = self.find_r(b)
        if (ra != rb):
            self.Set[rb] = ra
            self.Sum = self.Sum - 1
        return

    def get_set(self):
        '''
        返回一个list,每个元素是一个set
        '''
        Set = [None] * self.Sum
        cnt = 0

        lis = [None] * self.n
        for k in range(self.n):
            lis[k] = [k, self.find_r(k)]         # 把 节点,节点的根   这个tuple 存入lis
        lis.sort(key=lambda x: (x[1]))
        lis.append([-100, -100])  # 加一个终止条件?干啥用的....如果不加的话,下面for循环会少跑一次.因为显然节点pre里面不可能取到-100.所以这么加是没错的.

        pre = lis[0][-1]             # 编号最小的根
        pre_poi = 0

        for k in range(1, self.n + 1):
            if lis[k][-1] != pre:
                element_set = [None] * (k - pre_poi)
                for i in range(pre_poi, k):   # 从pre_poi 到k-1 都指向pre 因为上面的if条件.
                    element_set[i - pre_poi] = lis[i][0]
                Set[cnt] = np.array(element_set)
                cnt = cnt + 1 # cnt 表示武林门派的数量.  也就是根的数量.用的是左层云的比喻哈哈.
                pre = lis[k][-1]
                pre_poi = k

        return Set


if __name__ == '__main__':
    dis_join = DIS_JOIN()
    dis_join.clear(8)
    dis_join.join(0, 3)
    dis_join.join(1, 4)
    dis_join.join(0, 1)
    dis_join.join(2, 5)
    Set = dis_join.get_set()
    print(Set)
    # for k in range(5):
    #     print(k, dis_join.find_r(k))
    # print(dis_join.Sum)

    '''
    挺牛逼啊,做一下总结吧..
    
    运行完上面的结果.就会得到各个门派的分类结果.
    '''
View Code

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!