笔试算法题(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)次操作:操作分为:在末尾插入一 ...
随机推荐
- 02_电话拨号器intent说明
怎么在第一个Activity打开第二个Activity?在一个Activity中打开另外一个Activity,实际上之前已经做过,就是电话拨号器. package com.itheima.callne ...
- 【转载】CAS操作
[本文转载]http://blog.csdn.net/hsuxu/article/details/9467651 CAS CAS:Compare and Swap, 翻译成比较并交换. java.ut ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- 莫比乌斯反演总结——Chemist
懵逼乌斯反演果然名不虚传,自闭了两天的我打算学习一下这一块比较实用的数论内容. (注:1.为了区分狄尼克雷卷积与乘法,本篇文章中乘号全部省略,卷积全部用" * "表示.2.用gcd ...
- magento getMessage 不显示或者显示html标签解决方案
在模板页面不显示getMessage的解决方案是,在对应的控制器里加上如下代码: $this->_initLayoutMessages('customer/session'); 如果加入后出现如 ...
- php 静态绑定
简介 编辑 后期静态绑定 从PHP 5.3.0开始,PHP增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类. 该功能从语言内部角度考虑被命名为”后期静态绑定“.”后期绑定“的意思是说 ...
- 转】MongoDB主从复制实验 master/slave
原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/4/ 感谢! Posted: May 31, 2013 Ta ...
- 转】R利剑NoSQL系列文章 之 Hive
原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/3/ 感谢! Posted: Jul 27, 2013 Ta ...
- [转]无废话SharePoint入门教程二[SharePoint发展、工具及术语]
本文转自:http://www.cnblogs.com/iamlilinfeng/p/3186919.html 一.前言 1.由于上一篇文章的标题命名失误,此篇标题写给百度搜索”什么是SharePoi ...
- SP CAML工具
直接一直使用CAML做一些简单的SP列表查询,突然想对CAML进一步了解,于是找到两个常用工具,做以记录: 1 Caml Query Builder : 用于编写CAML查询,对初学者可以了解查询语句 ...