【算法与数据结构】并查集 Disjoint Set
并查集(Disjoint Set)用来判断已有的数据是否构成环。
在构造图的最小生成树(Minimum Spanning Tree)时,如果采用 Kruskal 算法,每次添加最短路径前,需要先用并查集来判断一下这个路径是否会构成环。
思路
遍历图的每一条边,按照下面的原则将对应的两个顶点添加到集合中:
- 如果两个顶点都不属于任一集合,则创建新的集合,并将这两个顶点放入
- 如果两个顶点都已经属于某个集合,则已经构成环,退出
- 如果有一个顶点已经属于某个集合,则将另一个顶点也加入这个集合
为了代码上的统一性,可以在开始前,把所有顶点都看成只有一个元素的集合,然后就是不停的合并集合。
集合可以用树的双亲表示法来表示,只需要额外创建一个数组即可。为了简化合并操作,可以每次都只操作两颗树的根结点。
int parent[n];
// 查找树的根结点
int findRoot(int parent[], int key) {
int root = key;
while (parent[root] != -1) {
root = parent[root];
}
return root;
}
// 合并树
int unionVertex(int parent[], int x, int y) {
int lRoot = findRoot(parent, x);
int rRoot = findRoot(parent, y);
// 两个结点的根结点为同一个,则这两个结点属于同一棵树
if (lRoot == rRoot) {
return 0;
}
// 否则,合并树,这里直接把左树作为右树的子树,可能会导致不平衡
parent[lRoot] = rRoot;
}
代码
为了在每次合并时,尽可能保证树的平衡,再创建一个数组保存树的高度,合并时将高度低的树作为子树即可。
#include <stdio.h>
void init(int parent[], int height[], int count) {
int i;
for (i = 0; i < count; i++) {
parent[i] = -1;
height[i] = 0;
}
}
int findRoot(int parent[], int key) {
int root = key;
while (parent[root] != -1) {
root = parent[root];
}
return root;
}
int unionVertex(int parent[], int height[], int x, int y) {
int lRoot = findRoot(parent, x);
int rRoot = findRoot(parent, y);
if (lRoot == rRoot) {
return 0;
}
// parent[lRoot] = rRoot;
if (height[lRoot] < height[rRoot]) {
parent[lRoot] = rRoot;
} else if (height[rRoot] < height[lRoot]) {
parent[rRoot] = lRoot;
} else {
parent[lRoot] = rRoot;
height[rRoot]++;
}
return 1;
}
int main(void) {
int edgeCount = 6, vertexCount = 5;
int i;
// 图中的边
int graph[5][2] = {
{0, 1}, {2, 4}, {1, 2}, {1, 3},
{2, 5}
};
int parent[edgeCount];
int height[edgeCount];
init(parent, height, edgeCount);
for (i = 0; i < vertexCount; i++) {
int ret = unionVertex(parent, height, graph[i][0], graph[i][1]);
if (ret == 0) {
printf("%d, %d\n", graph[i][0], graph[i][1]);
printf("find cycle!\n");
return 0;
}
}
printf("no find cycle!\n");
for (i = 0; i < vertexCount; i++) {
printf("%d's parent is: %d\n", i, parent[i]);
}
for (i = 0; i < vertexCount; i++) {
printf("%d's height is: %d\n", i, height[i]);
}
return 0;
}
执行结果:
no find cycle!
0's parent is: 1
1's parent is: 4
2's parent is: 4
3's parent is: 4
4's parent is: -1
0's height is: 0
1's height is: 1
2's height is: 0
3's height is: 0
4's height is: 2
【算法与数据结构】并查集 Disjoint Set的更多相关文章
- 算法手记 之 数据结构(并查集详解)(POJ1703)
<ACM/ICPC算法训练教程>读书笔记-这一次补上并查集的部分.将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code. 在一些有N个元素的集合应用问题中,通常会将每个元 ...
- ACM数据结构-并查集
ACM数据结构-并查集 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合 ...
- 【算法导论-36】并查集(Disjoint Set)具体解释
WiKi Disjoint是"不相交"的意思.Disjoint Set高效地支持集合的合并(Union)和集合内元素的查找(Find)两种操作,所以Disjoint Set中文翻译 ...
- 【数据结构】【计算机视觉】并查集(disjoint set)结构介绍
1.简述 在实现多图像无序输入的拼接中,我们先使用surf算法对任意两幅图像进行特征点匹配,每对图像的匹配都有一个置信度confidence参数,来衡量两幅图匹配的可信度,当confidence> ...
- 并查集(Disjoint Set)
在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.这一类问题其特点是看似并不复杂, ...
- POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )
Constructing Roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 19884 Accepted: 83 ...
- hdu 4641 K-string SAM的O(n^2)算法 以及 SAM+并查集优化
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末 ...
- hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)
还是畅通project Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化
转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...
随机推荐
- Ubuntu18.04 安装redis
Redis是常用基于内存的Key-Value数据库,比Memcache更先进,支持多种数据结构,高效,快速.用Redis可以很轻松解决高并发的数据访问问题:作为实时监控信号处理也非常不错. 安装red ...
- samba服务及vsftpd服务
如何配置多个网卡 第一步: 打开设置,选择网络驱动器添加 第二步: ip a 查看网卡是否添加成功 第三步: 打开刚添加的网卡配置文件(注意,你刚添加的网卡是没有配置文件的,需要去复制一份到/etc/ ...
- ROPE
#include <ext/rope> using namespace __gnu_cxx; ]; rope<int> x; rope<int> x(a,a + n ...
- Java并发编程实战 第10章 避免活跃性危险
死锁 经典的死锁:哲学家进餐问题.5个哲学家 5个筷子 如果没有哲学家都占了一个筷子 互相等待筷子 陷入死锁 数据库设计系统中一般有死锁检测,通过在表示等待关系的有向图中搜索循环来实现. JVM没有死 ...
- QT程序在发布的时候应注意的地方
---恢复内容开始--- 我们用QT开发好的应用程序,如果要发布到其他计算机上运行怎么办呢?我们在用VC编程时,单独运行编译好的可执行文件时,经常会发现提示缺少动态库.用QT编程也不例外,在一定程度上 ...
- shell之文本过滤(awk)
shell之文本过滤(awk) 分类: linux shell脚本学习2012-09-19 15:53 1241人阅读 评论(0) 收藏 举报 shell正则表达式脚本任务语言 如果要格式化报文或从一 ...
- 微信小程序-饮食日志_开发记录02
此段时间主要写功能的实现. 内部的增删改查等内容. 主要有食物查找.运动选择.身高体重比例计算等.
- 判断request中是否有文件
ServletFileUpload.isMultipartContent(request)
- Docker(1)--概述
Docker概述 Docker是一个用于开发,交付和运行应用程序的开放平台.Docker使您能够将应用程序与基础架构分开,从而可以快速交付软件.借助Docker,您可以以与管理应用程序相同的方式来管理 ...
- 第十二章 学习 shell脚本之前的基础知识
http://www.92csz.com/study/linux/12.htm [什么是shell] 简单点理解,就是系统跟计算机硬件交互时使用的中间介质,它只是系统的一个工具.实际上,在shell和 ...