数据结构《14》----并查集 Union-Find
2014-02-26 19:51
309 查看
描述:
并查集是一种描述解决等价关系。能够方便地描述不相交的多个集合。
支持如下操作 1. 建立包含元素 x 的集合 MakeSet(x)
2. 查找给定元素所在的集合 Find(x), 返回所在集合的代表
3. 将两个不相交的集合合并 Union(s1, s2)
本文参考《数据结构与算法分析,C语言描述》这本书,利用数组,给出了并查集的一个容易实现的版本。
采用了按秩合并 和 路径压缩 的方法加速。
数据结构:
用树表示一个集合,树的跟节点就是这个集合的代表元素。
并采用一维数组来非显示地模拟这个森林:
1. 数组长度是总的集合元素个数;
2. s[i] 表示元素 i 的父亲节点;
3. 如果 s[i] 是 负数,表示 i 就是代表元素; 并且负数的绝对值表示所在树的高度。(按高度压缩)
在这样的定义下,Find(x) 非常容易实现,只要从元素 x, 不断往上找,直到找到根节点返回即可。
![](https://img-blog.csdn.net/20140226193119109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hvdWxpbmp1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140226193141843?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hvdWxpbmp1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
按高度合并:
注意到,Find(x) 的复杂度是树的高度。
按高度合并就是通过将 矮的树 合并到 高的树作为其孩子,从而避免树过高。
路径压缩:
这种方法可以与按高度合并兼容,能够得到较高的效率。
它其实是在 Find(x) 这个函数做文章。
在搜索 x 所在树的 root 节点的过程中,将中途的节点都指向 root.
看了下图,大家就能明白了。
![](https://img-blog.csdn.net/20140226194827078?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hvdWxpbmp1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码非常简单:
完整的代码如下:
并查集是一种描述解决等价关系。能够方便地描述不相交的多个集合。
支持如下操作 1. 建立包含元素 x 的集合 MakeSet(x)
2. 查找给定元素所在的集合 Find(x), 返回所在集合的代表
3. 将两个不相交的集合合并 Union(s1, s2)
本文参考《数据结构与算法分析,C语言描述》这本书,利用数组,给出了并查集的一个容易实现的版本。
采用了按秩合并 和 路径压缩 的方法加速。
数据结构:
用树表示一个集合,树的跟节点就是这个集合的代表元素。
并采用一维数组来非显示地模拟这个森林:
1. 数组长度是总的集合元素个数;
2. s[i] 表示元素 i 的父亲节点;
3. 如果 s[i] 是 负数,表示 i 就是代表元素; 并且负数的绝对值表示所在树的高度。(按高度压缩)
在这样的定义下,Find(x) 非常容易实现,只要从元素 x, 不断往上找,直到找到根节点返回即可。
// return the disjoint set which x belongs to SetType Find(ElementType x, DisJointSet s) { if(s[x] < 0) return x; else return Find(s[x], s); }
按高度合并:
注意到,Find(x) 的复杂度是树的高度。
按高度合并就是通过将 矮的树 合并到 高的树作为其孩子,从而避免树过高。
//Assume root1 and root2 are roots void SetUnion(DisJointSet s, SetType root1, SetType root2) { if(s[root1] <= s[root2])//root1 is deeper than root2 { if(s[root1] == s[root2]) s[root1] --; s[root2] = root1; } else { s[root1] = root2; } }
路径压缩:
这种方法可以与按高度合并兼容,能够得到较高的效率。
它其实是在 Find(x) 这个函数做文章。
在搜索 x 所在树的 root 节点的过程中,将中途的节点都指向 root.
看了下图,大家就能明白了。
代码非常简单:
// return the disjoint set which x belongs to SetType Find(ElementType x, DisJointSet s) { if(s[x] < 0) return x; else return s[x] = Find(s[x], s); }
完整的代码如下:
/* dis-joint-set implemented by L.J. in Nov.11, 2013 */ /* union by height */ #include "disjointset.h" #include <iostream> using namespace std; const int NumSets = 8; typedef int DisJointSet[ NumSets + 1]; typedef int SetType; typedef int ElementType; void Initialize(DisJointSet s) { for(int i=NumSets; i>0; --i) s[i] = 0; } //Assume root1 and root2 are roots void SetUnion(DisJointSet s, SetType root1, SetType root2) { if(s[root1] <= s[root2])//roo1 is deeper than root2 { if(s[root1] == s[root2]) s[root1] --; s[root2] = root1; } else { s[root1] = root2; } } // return the disjoint set which x belongs to SetType Find(ElementType x, DisJointSet s) { if(s[x] < 0) return x; else return Find(s[x], s); }
相关文章推荐
- 数据结构《14》----并查集 Union-Find
- 并查集系列(二)——Union-find with specific canonical element
- 11987 - Almost Union-Find(并查集删除操作)
- 并查集(Union/Find)
- Union-Find(并查集): Union-Find Application
- UVA - 11987 - Almost Union-Find (又是并查集~)
- 并查集(Union-Find)算法介绍
- uva11987 Almost Union-Find(可删除元素的并查集)
- 并查集--Union_Find
- UVA11987_Almost Union-Find(并查集删除操作)
- 并查集 Union_Find_Set
- UVA 11987 - Almost Union-Find 并查集的活用 id化查找
- POJ 2492 A Bug's Life [数据结构-并查集 union-find sets]
- 并查集(Union-Find)算法介绍及例题讲解
- 并查集(Union-Find)算法介绍
- 并查集(删除) UVA 11987 Almost Union-Find
- Union-Find(并查集): Quick union算法
- 并查集(union-find set or DisjointSets)
- 并查集(Union-Find)算法介绍
- 并查集 (Union-Find Sets)