python实现一个简单的并查集的示例代码


Posted in Python onMarch 19, 2018

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。常常在使用中以森林来表示。

并查集有三种基本操作,获得根节点,判断两节点是否连通,以及将两不连通的节点相连(相当于将两节点各自的集合合并)

用UnionFind类来表示一个并查集,在构造函数中,初始化一个数组parent,parent[i]表示的含义为,索引为i的节点,它的直接父节点为parent[i]。初始化时各个节点都不相连,因此初始化parent[i]=i,让自己成为自己的父节点,从而实现各节点不互连。

def __init__(self, n):
    self.parent = list(range(n))

由于parent[i]仅表示自己的直接父节点,查询两个节点是否相交需要比较它们的根节点是否相同。因此要封装一个查询自己根节点的方法。

def get_root(self, i):
    while i != self.parent[i]:
      i = self.parent[i]

    return i

接下来可以通过来比较根节点是否相同来判断两节点是否连通。

def is_connected(self, i, j):
    return self.get_root(i) == self.get_root(j)

当要连通两个节点时,我们要将其中一个节点的根节点的parent,设置为另一个节点的根节点。注意,连通两个节点并非仅仅让两节点自身相连,实际上是让它们所属的集合实现合并。

def union(self, i, j):
    i_root = self.get_root(i)
    j_root = self.get_root(j)
    self.parent[i_root] = j_root

接下来我们做两个小优化。

由于调用get_root时需要通过不断找自己的直接父节点,来寻找根节点,如果这棵树的层级过深,会导致性能受到严重影响。因此我们需要在union时,尽可能的减小合并后的树的高度。

在构造函数中新建一个数组rank,rank[i]表示节点i所在的集合的树的高度。

因此,当合并树时,分别获得节点i和节点j的root i_root和j_root之后,我们通过访问rank[i_root]和rank[j_root]来比较两棵树的高度,将高度较小的那棵连到高度较高的那棵上。如果高度相等,则可以随便,并将rank值加一。

def union(self, i, j):
    i_root = self.get_root(i)
    j_root = self.get_root(j)

    if self.rank[i_root] == self.rank[j_root]:
      self.parent[i_root] = j_root
      self.rank[j_root] += 1
    elif self.rank[i_root] > self.rank[j_root]:
      self.parent[j_root] = i_root
    else:
      self.parent[i_root] = j_root

通过对union操作的改良可以防止树的高度过高。我们还可以对get_root操作本身进行优化。

当前每次执行get_root时,需要一层一层的找到自己的父节点,很费时。由于根节点没有父节点,并且文章开始处提到过如果一个节点没有父节点,那么它的父节点就是自己,因此可以说只有根节点的父节点是自己本身。现在我们加上一个判断,判断当前节点的父节点是否为根节点,如果不为根节点,就递归地将自己的父节点设置为根节点,最后返回自己的父节点。

def get_root(self, i):
    if self.parent[i] != self.parent[self.parent[i]]:
      self.parent[i] = self.get_root(self.parent[i])
    return self.parent[i]

以上是python实现一个简单的并查集的方式。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python处理文本文件实现生成指定格式文件的方法
Jul 31 Python
基于Python的XSS测试工具XSStrike使用方法
Jul 29 Python
如何在python中使用selenium的示例
Dec 26 Python
python3库numpy数组属性的查看方法
Apr 17 Python
下载python中Crypto库报错:ModuleNotFoundError: No module named ‘Crypto’的解决
Apr 23 Python
对Python中type打开文件的方式介绍
Apr 28 Python
基于Python List的赋值方法
Jun 23 Python
python 3.6.4 安装配置方法图文教程
Sep 18 Python
python使用Matplotlib画饼图
Sep 25 Python
PyCharm 创建指定版本的 Django(超详图解教程)
Jun 18 Python
Django框架中序列化和反序列化的例子
Aug 06 Python
Python一键安装全部依赖包的方法
Aug 12 Python
python使用筛选法计算小于给定数字的所有素数
Mar 19 #Python
python将每个单词按空格分开并保存到文件中
Mar 19 #Python
python将文本分每两行一组并保存到文件
Mar 19 #Python
python: line=f.readlines()消除line中\n的方法
Mar 19 #Python
Python File readlines() 使用方法
Mar 19 #Python
Python cookbook(数据结构与算法)筛选及提取序列中元素的方法
Mar 19 #Python
django用户注册、登录、注销和用户扩展的示例
Mar 19 #Python
You might like
[原创]PHP中通过ADODB库实现调用Access数据库之修正版本
2006/12/31 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
Javascript中自动切换焦点实现代码
2012/12/15 Javascript
Javascript加载速度慢的解决方案
2014/03/11 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
全屏js头像上传插件源码高清版
2016/03/29 Javascript
JavaScript定义全局对象的方法示例
2017/01/12 Javascript
页面缩放兼容性处理方法(zoom,Firefox火狐浏览器)
2017/08/29 Javascript
详解express + mock让前后台并行开发
2018/06/06 Javascript
bootstrap table列和表头对不齐的解决方法
2019/07/19 Javascript
python发送邮件的实例代码(支持html、图片、附件)
2013/03/04 Python
python 字符串格式化代码
2013/03/17 Python
python格式化字符串实例总结
2014/09/28 Python
Python脚本实现自动发带图的微博
2016/04/27 Python
Python编写电话薄实现增删改查功能
2016/05/07 Python
TensorFlow平台下Python实现神经网络
2018/03/10 Python
python简易远程控制单线程版
2018/06/20 Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
2018/07/04 Python
django认证系统实现自定义权限管理的方法
2019/08/28 Python
python实现身份证实名认证的方法实例
2019/11/08 Python
Python+OpenCV实现将图像转换为二进制格式
2020/01/09 Python
python和php哪个容易学
2020/06/19 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
Python远程方法调用实现过程解析
2020/07/28 Python
中国专业的综合网上购物商城:京东
2016/08/02 全球购物
GoPro摄像机美国官网:美国运动相机厂商
2018/07/03 全球购物
机械专业毕业生推荐信范文
2013/11/25 职场文书
2014年小学元旦活动方案
2014/02/12 职场文书
单位活动策划方案
2014/08/17 职场文书
2014年宣传工作总结
2014/11/18 职场文书
2014年管理工作总结
2014/11/22 职场文书
事业单位个人总结
2015/02/12 职场文书
开除员工通知
2015/04/22 职场文书
清明祭英烈活动总结
2015/05/11 职场文书
2015年重阳节活动主持词
2015/07/30 职场文书
Win11怎样将锁屏账户头像图片改成动画视频
2021/11/21 数码科技