笔试算法题(38):并查集(Union-Find Sets)
议题:并查集(Union-Find Sets)
分析:
一种树型数据结构,用于处理不相交集合(Disjoint Sets)的合并以及查询;一开始让所有元素独立成树,也就是只有根节点的树;然后根据需要将关联的元素(树)进行合并;合并的方式仅仅是将一棵树最原始的节点的父亲索引指向另一棵树;
优化:加入一个rank数组存储节点深度的下界(从当前节点到其最远子节点的距离),从而可以启发式的对树进行合并,从而减少树的深度,防止树的退化;使 得包含较少节点的树根指向包含较多节点的树根,具体指代为树的高度;另一个优化就是路径压缩,尽可能将子节点都直接连接到根节点之后;
并查集的空间复杂度为O(N),构建一个集合的时间复杂度为O(N);压缩后的查找复杂度是一个很小的常数;应用:Kruskal算法求最小生成树中判断新加入的边是否在同一棵树内部;两个节点的最近公共祖先(Least Common Ancestors);
初始化father:各个节点独立成树,并且其father[i]=i,也就是其父节点就是其自身;
father[i]
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9初始化rank:各个节点为根节点,所以高度都为1;
rank[i]
0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 1合并2和6:由于rank[2]=rank[6],所以将2的父亲索引指向6,这样2和6就在同一棵树;并需将6的rank值增加1;
father[i]
0 1 2 3 4 5 6 7 8 9
0 1 6 3 4 5 6 7 8 9
rank[i]
0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 2 1 1 1
样例:
int *father;
int *rank; /**
* 并查集的初始化:
* 数组father中的元素在最开始ide时候都是独立的树,也就是只有根节点
* 的树,数组father的下标i表示节点,而father[i]的值表示i节点的父亲
* 节点;rank[i]=1表示一开始所有树节点的高度都为1
* */
void init(int cap) {
father=new int[cap];
rank=new int[cap];
/**
* 时间复杂度为O(N)
* */
for(int i=;i<;i++) {
father[i]=i;
rank[i]=;
}
} void clean() {
delete [] father;
delete [] rank;
}
/**
* 查找元素所在的集合并进行路劲压缩:
* 由于需要频繁使用GetFather()函数,并且其时间复杂度受树结构影响;
* 当元素较多的时候,集合退化成链表,则GetFather()需要O(N),所以
* 需要对其进行优化,每次调用GetFather()的时候都将输入元素压缩成
* 最原始父亲节点的直接子节点
* */
int GetFather(int son) {
if(father[son]==son)
return son;
else {
father[son]=GetFather(father[son]);
return father[son];
}
} /**
* 合并两个不相交的集合:
* 输入元素x和y来自两个不相交的集合,找到其最原始的父亲节点
* 并将一个原始父亲节点设置为另一个原始父亲节点的父亲节点
* */
void Union1(int x, int y) {
/**
* GetFather()为递归寻找输入节点的最原始的父亲节点
* */
int fx=GetFather(x);
int fy=GetFather(y);
/**
* 判断x和y是否来自同一棵树,如果不是才进行赋值;其实可以
* 不同进行判断(省去if语句)
* 注意最原始父亲节点的father[i]=i;
* */
if(fx!=fy)
father[fx]=fy;
} /**
* 利用rank加权数组启发式进行合并
* */
void Union2(int x, int y) {
int fx=GetFather(x);
int fy=GetFather(y); if(fx==fy) return;
/**
* rank[fx]较大,说明其越靠近根节点,则将
* fy连接到其后面可以压缩路径
* */
if(rank[fx]>rank[fy])
father[fy]=fx;
else {
if(rank[fx]==rank[fy])
rank[fy]++;
father[fx]=fy;
}
} /**
* 判断两个元素是否属于同一个集合:
* 利用GetFather()函数判断其最原始父亲节点是否相同
* */
bool IsSameSet(int x, int y) {
return GetFather(x)==GetFather(y);
}
笔试算法题(38):并查集(Union-Find Sets)的更多相关文章
- 并查集(Union/Find)模板及详解
概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...
- 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 ...
- 前端如何应对笔试算法题?(用node编程)
用nodeJs写算法题 咱们前端使用算法的地方不多,但是为了校招笔试,不得不针对算法题去练习呀! 好不容易下定决心 攻克算法题.发现js并不能像c语言一样自建输入输出流.只能回去学习c语言了吗?其实不 ...
- PAT甲题题解-1107. Social Clusters (30)-PAT甲级真题(并查集)
题意:有n个人,每个人有k个爱好,如果两个人有某个爱好相同,他们就处于同一个集合.问总共有多少个集合,以及每个集合有多少人,并按从大到小输出. 很明显,采用并查集.vis[k]标记爱好k第一次出现的人 ...
- POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )
Constructing Roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 19884 Accepted: 83 ...
- 笔试算法题(50):简介 - 广度优先 & 深度优先 & 最小生成树算法
广度优先搜索&深度优先搜索(Breadth First Search & Depth First Search) BFS优缺点: 同一层的所有节点都会加入队列,所以耗用大量空间: 仅能 ...
- [Comet OJ - Contest #6 D][48D 2280]另一道树题_并查集
另一道树题 题目大意: 数据范围: 题解: 这个题第一眼能发现的是,我们的答案分成两种情况. 第一种是在非根节点汇合,第二种是在根节点汇合. 尝试枚举在第几回合结束,假设在第$i$回合结束的方案数为$ ...
- hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化
转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...
随机推荐
- tar 报错gzip: stdin: not in gzip format(转载)
转自:http://blog.sina.com.cn/s/blog_6f2274fb0100z026.html 今天在linux下 用tar -zxf xxx.tar.bz2 然后就报这个错. gzi ...
- Swift4 函数, 元组, 运算符
创建: 2018/02/19 完成: 2018/02/19 更新: 2018/02/25 修改标题 [Swift4 函数] -> [Swift4 函数, 元组, 运算符] 更新 :2018/03 ...
- SGU 176 Flow construction【有上下界最小流】
正好考到了所以翻一些题来做--猛然发现搞了半个月的网络流却没做两道上下界(不过这种题好像是比较少233) 首先建立超级源汇ss,tt,没限制的边照常连,对于有限制的边(u,v,mn,mx),连接(u, ...
- [ZPG TEST 108] Antimonotonicity【贪心】
T2:Antimonotonicity (Antimonotonicity.pas/in/out 128M 1s) 给你1-N的一个排列,数列中的数字互不相等,要求找出最长的子序列a,满足a1> ...
- flask-socketio 实现
Flask-SocketIO使Flask应用程序可以访问客户端和服务器之间的低延迟双向通信. 客户端应用程序可以使用Javascript,C ++,Java和Swift中的任何SocketIO官方客户 ...
- Linux环境下Apache反向代理金蝶中间件Apusic集群
操作系统:RedHat Enterprise Linux 5.6 文档参考:<金蝶Apusic应用服务器 帮助手册| IX. Apusic Http Server使用指南> 一.金蝶中间件 ...
- [转]在 Azure 云服务上设计大规模服务的最佳实践
本文转自:http://technet.microsoft.com/zh-cn/magazine/jj717232.aspx 英文版:http://msdn.microsoft.com/library ...
- 一段js实现复制文本内容到剪切板
<script type="text/javascript"> function copyUrl2() { var Url2=document.getElementBy ...
- Android基础TOP3:线性布局的特点,常用属性,及权重值
线性布局是一种让视图水平或者垂直布排列的布局: 常用属性: androuid:orientation :表示布局方向 取值vertical表示垂直布局 取值horizontal表示水平布局 andro ...
- GIS在石油行业中的应用
在石油工业中,发现新的石油资源,取得竞争优势,是成功的关键之一.GIS系统能帮助评估潜在的石油资源,及时.准确.直观地定位油气资源的空间分布及其特征,以正确有效地开展部署勘探开发工作,占领市场先机. ...