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备份文件以及mysql数据库的脚本代码
Jun 10 Python
Python简单实现控制电脑的方法
Jan 22 Python
Django学习教程之静态文件的调用详解
May 08 Python
python实现求两个字符串的最长公共子串方法
Jul 20 Python
对python实时得到鼠标位置的示例讲解
Oct 14 Python
基于python实现名片管理系统
Nov 30 Python
在django模板中实现超链接配置
Aug 21 Python
pytorch 数据处理:定义自己的数据集合实例
Dec 31 Python
Pytorch 实现focal_loss 多类别和二分类示例
Jan 14 Python
Python 简单计算要求形状面积的实例
Jan 18 Python
Python实现括号匹配方法详解
Feb 10 Python
在Python中字典按值排序的实现方法
Nov 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 字符串正则替换函数preg_replace使用说明
2011/07/15 PHP
写出高质量的PHP程序
2012/02/04 PHP
thinkPHP引入类的方法详解
2016/12/08 PHP
给大家分享几个常用的PHP函数
2017/01/15 PHP
php+croppic.js实现剪切上传图片功能
2018/08/14 PHP
PHP7 弃用功能
2021/03/09 PHP
对联广告js flash激活
2006/10/19 Javascript
Javascript模板技术
2007/04/27 Javascript
Jquery提交表单 Form.js官方插件介绍
2012/03/01 Javascript
jQuery动态地获取系统时间实现代码
2013/05/24 Javascript
详解wow.js中各种特效对应的类名
2017/09/13 Javascript
jQuery实现可兼容IE6的滚动监听功能
2017/09/20 jQuery
React Native日期时间选择组件的示例代码
2018/04/27 Javascript
vue-router 起步步骤详解
2019/03/26 Javascript
vue下使用nginx刷新页面404的问题解决
2019/08/02 Javascript
ES6中Promise的使用方法实例总结
2020/02/18 Javascript
小程序实现多个选项卡切换
2020/06/19 Javascript
JavaScript如何判断对象有某属性
2020/07/03 Javascript
[34:56]Ti4冒泡赛LGD vs Liquid 1
2014/07/14 DOTA
Python中for循环控制语句用法实例
2015/06/02 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
Python3.7实现中控考勤机自动连接
2018/08/28 Python
nohup后台启动Python脚本,log不刷新的解决方法
2019/01/14 Python
python中报错"json.decoder.JSONDecodeError: Expecting value:"的解决
2019/04/29 Python
英国最大的化装舞会服装网站:Fancydress.com
2017/08/15 全球购物
英国顶级水晶珠宝零售商之一:Tresor Paris
2019/04/27 全球购物
耐克奥地利官网:Nike奥地利
2019/08/16 全球购物
英国伦敦的睡衣品牌:Asceno
2019/10/06 全球购物
师范毕业生自我鉴定
2014/01/15 职场文书
保安岗位职责
2014/02/21 职场文书
大学生找工作求职信
2014/07/09 职场文书
医药销售自我评价200字
2014/09/11 职场文书
2015年班组建设工作总结
2015/05/13 职场文书
毕业生入职感言
2015/07/31 职场文书
私人贷款担保书该怎么写呢?
2019/07/02 职场文书
Python打包exe时各种异常处理方案总结
2021/05/18 Python