并查集(union-set)
来源:互联网 发布:windows 2008打开iis 编辑:程序博客网 时间:2024/06/08 16:43
应用:union/set及其应用
并查集是一种树形的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题,常常在使用中以森林表示。
1. 等价关系
具有自反性、对称性和传递性三个性质称为等价关系,如电气连通性。
给定一个等价关系“~”,基于以上性质,为判断是否a~b,只需验证a和b是否同属一个等价类,这给我们提供了解决等价问题的方法。
2. 基本操作
在初始化时使每个元素都属于一个集合,集合间不相交(disjoint)。
find: 返回给定元素的集合(即等价类)的名字;
union:使用求并操作添加关系,通常是先使用find判断二者是否已经有关系。
解决动态等价问题的方案有两种:一种是保证指令find能够以O(1)运行;另一种是保证union能以O(1)运行。二者不可兼得。
3. 数据结构实现和分析
3.1 find的O(1)可行性
要保证find的O(1)性,union就必须多做一些工作。一种方案是在每次union时扫描待合并集合,将其类名j全换成目标集合类名i,这样连续N-1次union的复杂度为O(N*N);另一种想法是将每个等价类放入一个链表中,可以节省更新时间,但减少不了实际的渐进时间;还有一种是合并过程中,将较小类的名字改成较大的等价类名字,这样任意顺序的M次find和N-1次union最多花费O(M+NlogN)。
3.2 union的O(1)可行性
1)naive结构
直接将root2的根改为root1,单次find最坏是O(N)
class DisjSets{public:explicit DisjSets(int numElements);int find(int x) const;int find(int x);void unionSets(int root1, int root2);private:vector<int> s;};//初始化所有元素为树根,分别代表一个单独的等价类DisjSets::DisjSet(int numElements): s(numElements){for (int i = 0; i < s.size(); i++ )s[i] = -1;}//rooti代表set_i的根,直接将rhs连到lhs的根上进行合并void DisjSets::unionSets(int root1, int root2){s[roo2] = root1;}//递归查找元素x的树根(即所属集合)int DisjSets::find(int x) const{if (s[x] <0)return x;else return find(s[x]);}2)按大小求并(union by size)
合并时总是使较小的树成为较大的树的子树,可以证明,任何节点的深度不会超过logN,单次find操作最坏为O(logN)。实现时通常让树根元素的值代表当前树的大小(树根都是负值)。
3)按高度求并(union by height)
合并时通过跟踪每棵树的高度(负值)使得浅树成为深度的子树,保证树的深度最多是O(logN) 。与按大小求并异曲同工。
//按高度求并void DisjSets::unionSets(int root1, int root2){if (-s[root1] < -s[root2]) //root2深于root1s[root1] = root2;else{if (s[root1] == s[root2])s[root1]--; //root1与root2高度相等,总体高度加1s[root2] = root1;}}4)find的路径压缩(path compression)
基本上说,union操作的任何算法都会产生相同的最坏情形的树(即find的O(logN)。此时要降低整体的复杂度,就需要再次从find函数下手。
一种方案是进行路径压缩,其效果是:每执行一次find函数,从x到树根上的每一个节点都使它的父节点变成树根。
int DisjSets::find(int x){if(s[x] < 0)return x;elsereturn s[x] = find(s[x]);}需要注意的是,路径压缩与按大小求并完全兼容(因为压缩后没有改变树的大小);但不与按高度求并兼容(因为改变了高度),由于无法准确计算压缩后数的高度,通常对于每棵树存储的高度都是估计值(称为“秩”),按秩求并理论上和按大小求并的效率是一样的。
可以证明,使用按秩求并和路径压缩探测方法最坏情况下几乎是线性的,最坏情况下需要的时间是,实际中一般,一个较弱的结果是O(MlogN)。
4. 应用
迷宫生成算法
《数据结构与算法分析 C++描述》原书第8章整理
- 并查集(union-set)
- 并查集(Union-Find Set)
- 并查集(union-find set or DisjointSets)
- 一、并查集 (Union-Find Set)
- 并查集(Union-Find Set)模板
- 并查集 Union-Find-Set
- 并查集(Union-Find Set)小结
- disjoint set (union-find set) (并查集)
- Union-Find Set 并查集 详解 [基本模板]
- 并查集(union-find set)与Kruskal算法
- 并查集(union-find set)hdoj/hdu 1232畅通工程
- 并查集算法(Union-Find)
- Union-Find 算法(并查集)
- 并查集:Union-Find(1)
- 并查集算法(union-find)
- 并查集(Union Find)
- 并查集(Union Find)简介
- uva11987Almost Union-Find (并查集)
- windows版svn安装说明
- vsftp与http共存目录
- 如何反编译android的apk文件得到资源文件
- 用ssh-keygen来设置ssh无密码登录
- docBase ="**\**\*.war"
- 并查集(union-set)
- wxWidgets String functions
- php浏览器下载文件 文件名 空格 中文 处理
- 专注力的重要性
- 基础篇总算结束了。
- 从notepad++ 到 sublime text2
- 白领是升职还是创业揭秘35岁前要做的10件事
- PHP中全局变量的使用global和$GLOBALS[]
- android init.c init.rc