1.4 线性表—并查集

什么是并查集

并查集是线性表的一种应用,是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。

结构

上面已经说明并查集是一种树型结构,所以可通过数组或者链表来实现,阿导在网上搜索了一下基本示例基本是通过数组来实现。

这样比较好模拟这种结构,下标为当前元素,然后数组里面的内容也为其组内成员。下面阿导以高度合并并查集为例
并查集结构

并查集的特性

  • 树型的数据结构

  • 最优情况下每个节点都指向根节点

  • 每个集有不同的代表

  • 具有传递性

操作

  • 判断两个元素是否属于同一组:public void isConnected(int x, int y)

判断两个元素是否属于同一组

直接查找到并查集的根就好了,若相等则在同一个组,否则不在同一个组。

  • 合并两个元素所在的组:public void unionElements(int x, int y)

合并两个元素所在的组

首先查询到两个元素的根,若相等则本身就在一个组无需处理,若不等则进行合并操作,首先判断两个组的树的高度,将矮的树和并到高的树,那样根的高度不会改变,若两个树的高度相等,则将作为根的高度自增加一处理

完整代码


package com.qucheng.qingtian.wwjd.datastructure;

/**
 * 并查集
 *
 * @author 阿导
 * @CopyRight 万物皆导
 * @Created 2019-12-04 16:49:00
 */
public class DaoUnionFindSet {
    /**
     * 当前下标的父亲是谁
     */
    private int[] parent;
    /**
     * 当前树的高度
     */
    private int[] rank;
    /**
     * 初始化数目
     */
    private int size;

    /**
     * 初始化集合
     *
     * @param size
     * @return
     * @author 阿导
     * @time 2019/12/4 :00
     */
    public DaoUnionFindSet(int size) {
        this.size = size;
        this.parent = new int[size];
        this.rank = new int[size];
        for (int i = 0; i < size; i++) {
            parent[i] = i;
            rank[i] = 1;
        }
    }

    /**
     * 查询当前元素的根
     *
     * @param cur
     * @return int
     * @author 阿导
     * @time 2019/12/4 :00
     */
    private int findParrent(int cur) {
        if (this.parent[cur] == cur) {
            return cur;
        }
        //压缩路径,第二次查询可以直接返回x的根而不用递归
        return this.parent[cur] = findParrent(this.parent[cur]);
    }

    /**
     * 判断两个元素是否存在同一个集合
     *
     * @param x
     * @param y
     * @return boolean
     * @author 阿导
     * @time 2019/12/5 :00
     */
    public boolean isConnected(int x, int y) {
        return this.findParrent(x) == this.findParrent(y);
    }

    /**
     * 合并两个元素所在的组
     *
     * @param x
     * @param y
     * @return void
     * @author 阿导
     * @time 2019/12/5 :00
     */
    public void unionElements(int x, int y) {
        // 获取 x 的根
        x = this.findParrent(x);
        // 获取 y 的根
        y = this.findParrent(y);
        // 若相等则就在同一组,不用处理
        if (x == y) {
            return;
        }
        // 若 y 的高度比较大,则将根的值设为 y,因此高度不会更改
        if (this.rank[x] < this.rank[y]) {
            this.parent[x] = y;
            return;
        }
        // 否则根的节点设置成 x
        this.parent[y] = x;
        // 要是两者高度一样, 则势必高度会增加 1
        if (this.rank[x] == this.rank[y]) {
            rank[x]++;
        }

    }


}


关注点

  • 并查集的操作

主要包含合并元素所在的组和判断两个元素是否在同一个组

  • 如何压缩路径

在查询根的时候,将当前下标的内容设置为数组内容里面下标的数组内容,即 this.parent[cur] = findParrent(this.parent[cur])

压缩路径

想了解的更多,不如转移到这篇文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值