并查集
来源:互联网 发布:js滤镜效果 编辑:程序博客网 时间:2024/06/03 18:43
以一个例子开始吧,我觉得这样比较好理解。如果Marry和Tom是亲戚,Tom和Ben是亲戚,你可以推出Marry和Ben是亲戚。再者,{1,2}两个点是连通的,{2,3}两个点也是连通的,当出现{1,3}这对点的时候,三个点就组成环了,这在Kruskal算法(最小生成树)中很有用。
我们使用并查集主要是为了寻找一个元素的代表,如下图所示,其中e就是集合{e,f,g}的代表,意思是,当进来一组新的集合,比如说是{g,a},这时要寻找第一个元素g的代表,那就是e了,然后寻找a的代表,如果二者代表一样,就是二者是亲戚。
根据上面所述的,并查集的基本操作分为:
1. makeSet(s):建立一个新的并查集,其中包含 s 个单元素集合。
2. unionSet(x, y):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并。
3. find(x):找到元素 x 所在的集合的代表,该操作也可以用于判断两个元素是否位于同一个集合,只要将它们各自的代表比较一下就可以了。
并查集是用树来表示集合的,但是这个树并没有表示为node*结点的形式,而是用两个数组来表示的,其中一个数组uset[]表示每个元素,rank[]则表示每个元素的秩,什么是秩呢?来看一下这用情况下图左边的这种情况:
当查找d的代表时,需要向上查找3次,也就是树的高度,这样很浪费时间,所以需要应用一种非常简单而有效的策略——路径压缩。路径压缩就是在每次查找时,令查找路径上的每个节点都直接指向根节点,对应图中右侧情况。将具有较小秩的树根指向具有较大秩的树根。简单的说,就是总是将比较矮的树作为子树,添加到较高的树中。也就是:
对应代码为:
const int MAXSIZE = 500;int uset[MAXSIZE];int rank[MAXSIZE]; void makeSet(int size) { for(int i = 0;i < size;i++) uset[i] = -1; for(int i = 0;i < size;i++) rank[i] = 0;}int find(int x) { if (uset[x] < 0) return x; uset[x] = find(uset[x]); return uset[x];}void unionSet(int x, int y) { if ((x = find(x)) == (y = find(y))) return; if (rank[x] > rank[y]) uset[y] = x; else { uset[x] = y; if (rank[x] == rank[y]) rank[y]++; }}
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- 使用awscli下载存储桶
- poj1094Sorting It All Out(拓朴排序)
- APUE 习题3-2 实现dup2,要求不使用fcntl函数。
- android studio checkbox隐藏和显示在recyclerview中
- 驱动级别 进程隐藏pid
- 并查集
- linux配置maven
- Treelist数据能获取但是显示不出来
- stringbuffer与stringbuilder的区别
- Android基类Activity的设计
- Java Web 中使用ffmpeg实现视频转码、视频截图,javaffmpeg
- oracle表分区详解
- android studio关闭启动时indexing
- REDIS学习(3.2)spring boot 使用redis作为缓存