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使用json序列化datetime类型实例解析
Feb 11 Python
对python 矩阵转置transpose的实例讲解
Apr 17 Python
python Dijkstra算法实现最短路径问题的方法
Sep 19 Python
vscode 配置 python3开发环境的方法
Sep 19 Python
nginx搭建基于python的web环境的实现步骤
Jan 03 Python
Python基础之字符串操作常用函数集合
Feb 09 Python
python对数组进行排序,并输出排序后对应的索引值方式
Feb 28 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
Feb 29 Python
关于python的缩进规则的知识点详解
Jun 22 Python
python 字符串格式化的示例
Sep 21 Python
Python字节单位转换(将字节转换为K M G T)
Mar 02 Python
python munch库的使用解析
May 25 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
数字转英文
2006/12/06 PHP
THINKPHP内容分页代码分享
2015/01/14 PHP
php遍历CSV类实例
2015/04/14 PHP
PHP封装的XML简单操作类完整实例
2017/11/13 PHP
jQuery setTimeout()函数使用方法
2013/04/07 Javascript
父节点获取子节点的字符串示例代码
2014/02/26 Javascript
超级简单的jquery操作表格方法
2014/12/15 Javascript
jQuery打字效果实现方法(附demo源码下载)
2015/12/18 Javascript
20分钟成功编写bootstrap响应式页面 就这么简单
2016/05/12 Javascript
javascript简单进制转换实现方法
2016/11/24 Javascript
JavaScript构建自己的对象示例
2016/11/29 Javascript
实例详解JavaScript中setTimeout函数的执行顺序
2017/07/12 Javascript
Bootstrap实现翻页效果
2017/11/27 Javascript
Angular 项目实现国际化的方法
2018/01/08 Javascript
p5.js实现斐波那契螺旋的示例代码
2018/03/22 Javascript
vue-cli 引入jQuery,Bootstrap,popper的方法
2018/09/03 jQuery
angular 未登录状态拦截路由跳转的方法
2018/10/09 Javascript
使用ESLint禁止项目导入特定模块的方法步骤
2019/03/04 Javascript
Django如何防止定时任务并发浅析
2019/05/14 Python
python读取并写入mat文件的方法
2019/07/12 Python
Python 3.8 新功能大揭秘【新手必学】
2020/02/05 Python
python 浮点数四舍五入需要注意的地方
2020/08/18 Python
Selenium Webdriver元素定位的八种常用方式(小结)
2021/01/13 Python
1688平价精选商城:阿里集团旗下,工厂出厂价格直销
2017/04/24 全球购物
Pam & Gela官网:美国性感前卫女装品牌
2018/07/19 全球购物
巴西最大的玩具连锁店:Ri Happy
2020/06/17 全球购物
法律专业应届生自荐信范文
2014/01/06 职场文书
《荷花》教学反思
2014/04/16 职场文书
中学生民族团结演讲稿
2014/08/27 职场文书
商业用房租赁协议书
2014/10/13 职场文书
营销与策划实训报告
2014/11/05 职场文书
消防安全培训工作总结
2015/10/23 职场文书
Nginx搭建rtmp直播服务器实现代码
2021/03/31 Servers
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang
Tomcat starup.bat 脚本实现开机自启动
2022/04/20 Servers
vue递归实现树形组件
2022/07/15 Vue.js