【算法与数据结构】——并查集
参考算法与数据结构——并查集
同时加入了一些自己的理解,简化了很多。侵删。
概论
定义:
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。
主要构成:
并查集主要由一个整型数组pre[ ]和两个函数find( )、join( )构成。
数组 pre[ ] 记录了每个点的前驱节点是谁,函数 find(x) 用于查找指定节点 x 属于哪个集合,函数 join(x,y) 用于合并两个节点 x 和 y 。
作用:
并查集的主要作用是求连通分支数(如果一个图中所有点都存在可达关系(直接或间接相连),则此图的连通分支数为1;如果此图有两大子图各自全部可达,则此图的连通分支数为2……)
并查集的初始化
将所有元素的前驱都设为他自己。
find()函数
我们需要定义一个数组:int pre[1000]; (数组长度依题意而定)。这个数组记录了每个元素的前驱结点是谁。比如说pre[16]=6就表示16号元素的前驱结点是6号。如果一个元素的前驱结点就是他自己,那说明他就是代表元了,查找到此结束。也有一个元素自及组成一个集合的,那么这个集合的代表元就是自己。
int find(int x) //查找x的代表元
{while(pre[x] != x) //如果x的前驱结点不是自己x = pre[x];return x;
}
join函数
join函数的作用是将两个集合合并,合并两个集合的关键是找到两个集合的代表元,将其中一个作为另一个的前驱结点即可。
void join(int x,int y)
{int fx=find(x), fy=find(y); if(fx != fy) pre[fx]=fy; //fy做fx的前驱结点
}
千万注意不要直接将读入的两个数据,其中一个作为另一个的前驱结点,而应该是找到两个数据的代表元,将两个代表元合并,也就是将两个集合合并。
路径压缩算法:优化find( )函数
这里并没有明确谁是谁的前驱的规则,而是我直接指定后面的数据作为前面数据的前驱。那么这样就导致了最终的树状结构无法预计,即有可能是良好的 n 叉树,也有可能是单支树结构(一字长蛇形)。试想,如果最后真的形成单支树结构,那么它的效率就会及其低下(树的深度过深,那么查询过程就必然耗时)。
而我们最理想的情况就是所有人的直接上级都是教主,这样一来整个树的结构就只有两级,此时查询教主只需要一次。因此,这就产生了路径压缩算法。
实现:
从上面的查询过程中不难看出,当从某个元素出发去寻找它的代表元时,我们会途径一系列的元素,在这些节点中,除了代表元外,其余所有节点都需要更改直接前驱为曹操。
因此,基于这样的思路,我们可以通过递归的方法来逐层修改返回时的某个节点的直接前驱(即pre[x]的值)。简单说来就是将x到根节点路径上的所有点的pre(上级)都设为根节点。下面给出具体的实现代码:
int find(int x) //查找结点 x的根结点
{if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点 return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后pre[x]=rootx
}
该算法存在一个缺陷:只有当查找了某个元素的代表元后,才能对该查找路径上的各节点进行路径压缩。换言之,第一次执行查找操作的时候是实现没有压缩效果的,只有在之后才有效。
路径压缩算法:加权标记法
主要思路:
加权标记法需要将树中所有节点都增设一个权值,用以表示该节点所在树中的高度(比如用rank[x]=3表示 x 节点所在树的高度为3)。这样一来,在合并操作的时候就能通过这个权值的大小来决定谁当谁的前驱结点。
在实际写代码时,为了使代码尽可能简洁,我们可以将第1点单独作为一个逻辑选择,然后将2、3点作为另一个选择(反正第2点任意指定上级嘛),所以具体的代码如下:
void union(int x,int y)
{x=find(x); //寻找 x的代表元x=find(y); //寻找 y的代表元if(x==y) return ; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,直接返回;否则,执行下面的逻辑if(rank[x]>rank[y]) pre[y]=x; //如果 x的高度大于 y,则令 y的上级为 xelse //否则{if(rank[x]==rank[y]) rank[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1pre[x]=y; //让 x的上级为 y}
}
【算法与数据结构】——并查集相关推荐
- 算法与数据结构——并查集
文章推荐:[算法与数据结构]-- 并查集 例子: 数据结构--最小生成树之克鲁斯卡尔算法(Kruskal) 1.2 并查集思想(重点) 我们可以把每个连通分量看成一个集合,该集合包含了连通分量的所有点 ...
- (转载)一种简单而有趣的数据结构——并查集
一种简单而有趣的数据结构--并查集 作者:goal00001111(高粱) 一个秘密生物武器落到某地区,导致当地村民丧失部分记忆,只认得自己最熟悉的人,而忘记自己是哪个村子的人了.大家汇集到一个广场, ...
- 一种简单而有趣的数据结构——并查集
一种简单而有趣的数据结构--并查集 作者:goal00001111(高粱) 一个秘密生物武器落到某地区,导致当地村民丧失部分记忆,只认得自己最熟悉的人,而忘记自己是哪个村子的人了.大家汇集到一个广场, ...
- 【算法训练营】 - ⑩ 并查集与图
[算法训练营] - ⑩ 并查集与图 并查集 并查集特征 并查集的优化 图 图结构的表达 图的面试题如何搞定? 图的数据结构 点 边 图 生成图 图算法 广度优先遍历 深度优先遍历 图的拓扑排序算法 最 ...
- 基于C语言,详解Kruskal算法(利用并查集)实现构建最小生成树
目录 一.Kruskal算法的基本介绍 具体做法:找出森林中连接任意两棵树的所有边中,具有最小权值的边,如果将它加入生成树中不产生回路,则它就是生成树中的一条边.这里的关键就是如何判断"将它 ...
- 高级数据结构---并查集
高级数据结构-并查集 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> #define N 100 int father ...
- 【数据结构与算法基础】并查集原理、封装实现及例题解析(C和java)
前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...
- mst算法matlab_基于并查集+Kruskal算法的matlab程序及最小生成树绘图
学了一天最小生成树,稍稍总结一下,这是第一篇 kruskal算法 关于kruskal算法已有大量的资料,不再赘述,算法流程为: 得到邻接矩阵和权值: 初始化,连接距离最小的两点: 连接距离次小的两点, ...
- 数据结构---并查集
并查集,顾名思义,合并 查找 集合: 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 对于概念等等的这里不再赘述,直接讲解 ...
- Kruskal算法:贪心+并查集=最小生成树
http://www.51nod.com/ Kruskal算法的高效实现需要一种称作并查集的结构.我们在这里不介绍并查集,只介绍Kruskal算法的基本思想和证明,实现留在以后讨论. Kruskal算 ...
最新文章
- 如何做好产品经理一:你们是傻的吗?
- ASP.NET Core 3.0 项目开始“瘦身”
- 从0到1使用VUE-CLI3开发实战(五):模块化VUEX及使用vuetify
- String s = new String(xyz)创建了几个实例你真的能答对吗?
- CentOS下Composer的安装和使用
- Oracle中ascii为0的陷阱
- 图标,专业设计师基本素材要件
- 没有计算机基础可以学python-学习第一天day1(计算机基础,及python基础)
- 干货 | 找工作的经验总结(一)
- Python各系统的安装
- 为什么机器学习行业的发展离不开 “开源”
- Xcode 与 macOS 系统版本的兼容问题
- 使用Python和MySQL实现网上购物管理系统
- Oracle安装过程中出现的错误指令
- 一切从零开始------软件篇
- PHP 实现网页爬虫
- 华为鸿蒙,希望是务实的操作系统
- WiFi的2.4G、5G、6G频段
- 远程往服务器上传送文件,服务器远程传送文件
- unity android 性能分析,Unity Profiler 性能分析