ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

并查集

2021-01-31 10:30:26  阅读:157  来源: 互联网

标签:p2 p1 int 查集 public parents find


1. 简介

  1. 并查集(Union Find)也叫做不相交集合
  2. 并查集有两个核心操作
    1. 查找(Find):查找元素所在集合
    2. 合并(Union):将两个元素所在集合合并为一个集合
  3. 两种常见实现思路
    1. QuickFind:查找 —— O(1),合并 —— O(n)
    2. QuickUnion(常用):查找 —— O(logn)可优化至O(5),合并 —— O(logn)可优化至O(5)

2. 并查集如何存储数据

以存储整形数据为例,可以用数组实现并查集。比如数组的索引表示数据,值代表所属集合。
、

3. 实现

3.1 初始化

	private int[] parents; 
    public UnionFind(int capacity){
        parents = new int[capacity];
        //每个数据单独属于一个集合
        for(int i=0;i<parents.length;i++){
            parents[i] = i;
        }
    }

3.2 基于QuickFind的Union、Find操作

在这里插入图片描述

union(1,0)是指将1的结点改为0的父结点,即将1所在集合并入0所在集合。

    public void union(int v1, int v2){
        int p1 = find(v1);
        int p2 = find(v2);
        if(p1 == p2){
            return;
        }
        for (int i = 0; i < parents.length; i++) {
            if(parents[i] == p1){
                parents[i] = p2;
            }
        }
    }
    
    public int find(int v){
        return parents[v];
    }

这种情况下实现的并查集,其相应的树的高度最多为2,所以查找时间短

3.3 基于QuickUnion

3.3.1 Union、Find操作

在这里插入图片描述
union(1,0)是指将1的结点改为0的父结点,即将1所在集合并入0所在集合。

	public void union(int v1, int v2){
        int p1 = find(v1);
        int p2 = find(v2);
        if(p1 == p2){
            return;
        }
        parents[p1] = p2;
    }
    
    public int find(int v){
        while(v != parents[v]){
            v = parents[v];
        }
        return v;
    }
3.3.2 Union、Find操作的优化
  1. 优化点:在合并过程中可能会出现树不平衡的状况,甚至退化成链表
    在这里插入图片描述

  2. 方案

    1. 基于size:元素少的树 嫁接到 元素多的树
    	int[] sizes = new int[capacity];
    	Arrays.fill(sizes,1);
    	
    	public void union_s1(int v1, int v2){
            int p1 = find(v1);
            int p2 = find(v2);
            if(p1 == p2){
                return;
            }
            if(sizes[p1] < sizes[p2]){
                parents[p1] = p2;
                sizes[p2] += sizes[p1];
            }else{
                parents[p2] = p1;
                sizes[p1] += sizes[p2];
            }
        }
    
    1. 基于rank: 矮的树 嫁接到 高的树
    	int[] ranks= new int[capacity];
    	Arrays.fill(ranks,1);
        public void union_s2(int v1, int v2){
            int p1 = find(v1);
            int p2 = find(v2);
            if(p1 == p2){
                return;
            }
            if(ranks[p1] < ranks[p2]){
                ranks[p1] = p2;
            }else if(ranks[p1] > ranks[p2]){
                ranks[p2] = p1;
            }else{
                parents[p1] = p2;
                ranks[p2]++;
            }
    	}
    
  3. 路径压缩

    1. 随依然有了基于rank的优化,树相对会平衡些,但随着Union的次数增多,树的高度依然会越来越高,这就导致了find操作时间复杂度变高
    2. 使用路径压缩可解决这一问题。路径压缩是指,在find()时使路径上的所有结点都指向根节点,从而降低树的高度
    public int find_s(int v){
        if(parents[v] != v){
            parents[v] = find(parents[v]);
        }
        return parents[v];
    }
    
  4. 更优的做法
    虽然路径压缩可以降低树的高度,但是由于调用了递归,在优化树的高度过程中依然会付出一些代价。接下来介绍的两种方法,在降低树的高度的同时有着更小的代价。

    1. 路径分裂:是路径上的每个结点都指向其祖父节点
      在这里插入图片描述
        public int find_s1(int v){
            while(v != parents[v]){
                int p = parents[v];
                parents[v] = parents[p];
                v = p;
            }
            return v;
        }
    
    1. 路径减半:是路径上每隔一个结点就指向其祖父节点
      在这里插入图片描述
        public int find_s2(int v){
            while(v != parents[v]){
                parents[v] = parents[parents[v]];
                v = parents[v];
            }
            return v;
        }
    

3.4 isSame操作,判断是否属于同一集合

    public boolean isSame(int v1, int v2){
        int p1 = find(v1);
        int p2 = find(v2);
        return p1==p2;
    }

标签:p2,p1,int,查集,public,parents,find
来源: https://blog.csdn.net/qq_42451178/article/details/113448044

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有