并查集
来源:互联网 发布:公众号助手电脑版 mac 编辑:程序博客网 时间:2024/06/06 19:45
并查集(Union-find set),从字面上来看就是支持合并(union),查找(find) 的集合嘛。下面我们来学习一下这种数据结构
并查集的精髓(即它的三种操作,结合实现代码模板进行理解):
1、Make_Set(x) 把每一个元素初始化为一个集合
初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。
2、Find_Set(x) 查找一个元素所在的集合
查找一个元素所在的集合,其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。
判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
合并两个集合,也是使一个集合的祖先成为另一个集合的祖先,具体见示意图
3、Union(x,y) 合并x,y所在的两个集合
合并两个不相交集合操作很简单:
利用Find_Set找到其中两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。如图
for(int i=1;i<=n;i++)
parent[i]=i;
下面看看并查集的核心Find_Set(x),其实这个操作并不只是简单的查找祖先的操作还有路径压缩的操作,以下图为例
假设我们在查找a的祖先,找到了d,而b,c,的祖先都是d,但是我们可能下一次要查找b的祖先,但是依然要从b往上面递归,显然次数多了,时间就多了,其实我们在之前查找a的祖先的时候,已经知道了b的祖先是d,这时候便有了我们的路径压缩操作。
看一下查找的一些操作
这是朴素查找的代码,适合数据量不大的情况:int findx(int x){int r=x;while(parent[r] !=r)r=parent[r];return r;}下面是采用路径压缩的方法查找元素:int find(int x) //查找x元素所在的集合,回溯时压缩路径{if (x != parent[x]){parent[x] = find(parent[x]); //回溯时的压缩路径} //从x结点搜索到祖先结点所经过的结点都指向该祖先结点return parent[x];}上面是一采用递归的方式压缩路径, 但是,递归压缩路径可能会造成溢出栈,下面我们说一下非递归方式进行的路径压缩:int find(int x){int r,tem;r = x;while(r != parent[r]) //查找跟节点r = parent[r]; //找到跟节点,用r记录下 while(x != r) //非递归路径压缩操作{ tem=parent[x]; parent[x]=r; x=tem; }return x; //返回根节点的值 }最后看看合并的操作
void Unionset(int x,int y){ int x1 = Find(x),y1 = Find(y); if(x1>y1) parent[x1] = y1; else parent[y1] = x1;}
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- service生命周期
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- tool list
- Mac 下配置php环境
- 开发者需知的10类工具
- 并查集
- Linux下的ELF可执行文件的格式解析
- vim 插件:perl-support的修改和使用
- Android 仿 WP7 布局
- the different between C and C++
- AS3嵌入swf元件库,如何访问指定的资源
- 使用Ant来编译Flex应用
- Flex mxmlc编译命令选项
- Into Clause VS Let Clause