并查集及其算法实现
来源:互联网 发布:安庆2017网络效应答案 编辑:程序博客网 时间:2024/05/22 00:22
1、算法思想:转自:http://blog.csdn.net/hpuhjh/article/details/47832795
一、算法介绍:
并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题。
并查集的基本操作有两个:
1:合并
union(x, y):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果两个集合相交则不合并。
2:查询
find(x):找到元素 x 所在的集合的代表,该操作常用于判断两个元素是否位于同一个集合,只要将它们各自的代表比较一下就可以了。
并查集类似一个森林,是用树形结构来实现的,所以以下的讲解用树形结构来构造模型:
事先声明:
(1)一个集合对应一棵树。
(2)一个集合中的元素对应一个节点。
二、算法实现:
一、初始化:
我们用n个节点表示n个元素,有一点要特别注意:一个节点,若它的父节点等于它本身,则说明这个节点是根节点。
定义数组 per[], per[x]代表x的父节点。初始化时我们把per[x] = x,相当于每个节点都是独立的根节点(每个根节点都代表一个集合)
二、查找:
find(x),查找元素x所在的集合,即查找节点x在哪一棵树上,这里我们知道,在一棵树中,根节点是唯一的,父节点子节点都是相对而言的。要想确定节点x在哪一课树,我们只需要找到x的根节点就可以了。
如果判断节点x 和 节点y在不在同一棵树上,我们只需要找到x 和 y的根节点,若x和y的根节点相同,则x,y在同一颗树上,否则在不用的树上。
代码:
图1.1
如图1.1所示:
我们令节点1为根节点。查找节点4在哪一棵树,我们只要找到4的根节点就可以了。
查找过程: 找到4的父节点per[4]为2,不等于它本身,继续向上查找, 2它的父节点per[2]为1,不等于它本身,继续向上查找,1的父节点per[1]为1等于它本身,说明1是根节点。
这里有一个路径压缩的优化, 当我们查找到4的根节点为1时,我们直接将per[4] = 1,即直接把4连在根节点1上,而且在查找4时还会找到2,可能还有其他的节点,将这些节点的per[]通通都设置为1,这样下次再查找4的子节点所在的树时,查找次数就缩短了1.
这里压缩路径有两种写法,一种是递归的,一种是非递归的。
1> 递归:
2>非递归
请读者自己模拟一下这两种压缩路径的方式不同之处在于:只是各个节点修改父节点的顺序不同而已。递归方法:先修改距离父节点近的节点,这由递归性质决定的;非递归方法:先修改离父节点最远的节点。
三、合并:
合并x 和 y所在的树, 只需要把其中一个树的根节点设置为令一个树根节点的子节点即可;
但是这里有一个问题, 是把 x的根节点设置为 y根节点的子节点,还是把y的根节点设置为x根节点的子节点。
节点1和节点2是一棵树,根节点为1, 节点3是一棵树,根节点是自身为3.
图1.2
图1.3
如图1.2所示:
现在我们根节点3作为根节点1的子节点,此时查找2的根节点,只需要查找一次。
如图1,3所示
现在我们根节点1作为根节点3的子节点,此时查找2的根节点,需要先找到1,再找到3,多了一次查找。
所以这里存在一种优化。我们可以设置一个数组rank[ ],用它来记录每一棵树的深度,合并时如果两棵树的深度不用,那么从深度(rank)小的向深度(rank)达的连边。(但注意,压缩路径时会使树的深度发生变化,但我们不修改rank 的值)
2、牛客网刷题:
题目描述
输入描述:
第一行包含两个整数N(1≤N≤10000),M(1≤M≤1000000)。N表示公有N块空地。接下来M行,每行包含两个整数P(1≤P≤N),Q(1≤Q≤N),K代表P,Q两个间没有鳄鱼,需要耗费K的木材。
输出描述:
一个整数,即耗费木材最少的情况下,最长的那根木材长度。
输入
4 31 2 12 3 13 4 2
输出
2
package schooloffer;import java.util.Arrays;import java.util.Comparator;import java.util.Scanner;/** * Created by caoxiaohong on 17/9/21. * 亮亮解出了卷轴隐藏的秘密,来到了一片沼泽地。这里有很多空地,而面试直通卡可能埋在任意一块空地中,好在亮亮发现了一堆木材,.... * 算法思想:并查集+最小生成树 * 求:最小生成树中:权值最大的那个路径 */public class SearchTreasure { static class Edge{ private int x; private int y; private int weight; Edge(int x,int y,int weight){ this.x=x; this.y=y; this.weight=weight; } } public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int N,M; while (scanner.hasNext()){ String[] str=scanner.nextLine().split(" "); N=Integer.valueOf(str[0]); M=Integer.valueOf(str[1]); Edge[] values=new Edge[M]; for(int i=0;i<M;i++){ String[] w=scanner.nextLine().split(" "); int x=Integer.valueOf(w[0]); int y=Integer.valueOf(w[1]); int weight=Integer.valueOf(w[2]); Edge edge=new Edge(x,y,weight); values[i]=edge; } System.out.println(solution(values,N,M)); } } //并查集:初始化 private static void init(int[] father,int n){ for(int i=0;i<=n;i++) father[i]=i; } //并查集:查找根节点 private static int getFather(int[] father,int x){ int r=x; while (father[r]!=r) // father[x]=y:表示x点对应对根节点为y r=father[r]; //压缩路径: int i=x; while (i!=r) { int j=father[i]; father[i]=r; i=j; } return r; } //并查集:合并 private static void mergeSet(int[] father,int fx,int fy){ if(fx>fy){ father[fx]=fy; }else { father[fy]=fx; } } //总算法 private static int solution(Edge[] values,int n,int m){ int result=0; //初始化 int[] father=new int[n+1]; init(father,n); //对valuse[]按照weight排序 Arrays.sort(values, new Comparator<Edge>() { @Override public int compare(Edge o1, Edge o2) { return o1.weight-o2.weight; } }); for(int i=0;i<m;i++){ int fx=getFather(father,values[i].x); int fy=getFather(father,values[i].y); if(fx!=fy){ if(result<values[i].weight) result=values[i].weight; //合并节点 mergeSet(father,fx,fy); } } return result; }}
- [算法] 并查集概念及其实现
- 并查集及其算法实现
- 小谈并查集及其算法实现
- 并查集概念及其实现
- 并查集的使用及其实现
- 并查集及其简单应用:优化kruskal算法
- 使用并查集实现Kruscal算法
- Kruskal算法+并查集实现
- 并查集实现Kruskal算法
- Kruskal算法的并查集实现
- java实现并查集算法
- [容易] kruskal 算法并查集实现
- 并查集及其应用
- 并查集及其应用
- 并查集及其应用
- 并查集及其应用
- 并查集及其应用
- 并查集及其应用
- Linux常用命令(工具)
- spark-调优-JVM
- ArrayList源码解析
- matlab 空数组的赋值
- centos7.1 RabbitMQ安装配置
- 并查集及其算法实现
- flume 配置插件
- 信管16数据结构:第三章栈和队列的课前翻转学习任务
- [LeetCode]46. Permutations
- Java IO流 进行文件复制
- 安装vmware-tools出现"what is the location of the "ifconfig"program on your machine?"
- 从零开始前端学习[14]:选择器的优先级
- 图像处理基本算法(汇总)以及实现
- SCUT Training 20170920 Problem D