并查集 (Union-Find)

问题现象

并查集算法主要是用来解决动态连通性问题

动态连通性(Dynamic Connectivity)

根据《Algorithms4》可知,动态连通性即给定N个对象的集合,可以做以下操作:

  • Union操作:连接两个对象
  • Find/connected查询: 两个对象是否连接?

其中,连通具有以下性质:

  • Reflexive: p和p是相连的,又称自反性;
  • Symmetric: 如果p和q是相连的,那么q和p也是相连的,又称对称性;
  • Transitive: 如果p和q相连且q和r相连,那么p和r相连,又称传递性。

问题建模

API

public class UnionFind {int[] parent; // 存储某个对象的父节点,大小为N,初始化为对应的数组下标,代表独立分量,且是树根,也即初始化为parent[i] = i;UnionFind(int N) { // 构造函数}public void union(int p, int q) { // 连通 q, p分量}private int find(int x) { // 获取x的根节点}public boolean connected(int p, int q) { // 判断q, p是否连通}public int count() { // 获取连通分量个数}
}

find方法

    private int find(int x) { // 获取x的根节点while (x != parent[x]) { // 根节点的数组值就是自身的下标,也就是parent[x] = xx = parent[x];}return x;}

union方法

    public void union(int p, int q) { // 连通 q, p分量int rootQ = find(q);int rootP = find(p);if (rootP == rootQ) { // 若根节点相同,则说明两个分量已相连,直接返回return;}parent[rootQ] = rootP; // 将Q的根节点连接到P的根节点上,也可以parent[rootP] = rootQ}

优化

从上述代码可知,union方法是直接将某棵树的根节点连接在另一棵树上,在多次执行此操作后,树可能会很高,甚至退化成链表。而find方法是从某一个节点往上依次遍历到根节点,若树的高度很高,则会导致查找效率低下。

find方法优化

  • 隔代压缩:把路径上的每个节点的父节点指向其祖父节点
    private int find(int x) { // 获取x的根节点while (x != parent[x]) { // 根节点的数组值就是自身的下标,也就是parent[x] = xparent[x] = parent[parent[x]];x = parent[x];}return x;}
  • 彻底压缩:先找到当前结点的根结点,然后把沿途上所有的节点都指向根节点
    private int find(int x) { // 获取x的根节点if (x != parent[x]) { // 根节点的数组值就是自身的下标,也就是parent[x] = xparent[x] = find[parent[x]];}return x;}

union方法优化

增加一个数组,大小为N,初始化为对应的数组下标,也即初始化为size[i] = i,记录每棵树的高度,在查找的时候比较树高,高度小的树合并到高度搞的树上,相等的话两者均可作为根节点,并把高度加一;

    public void union(int p, int q) { // 连通 q, p分量int rootQ = find(q);int rootP = find(p);if (rootP == rootQ) { // 若根节点相同,则说明两个分量已相连,直接返回return;}if (size[rootP] > size[rootQ]) {parent[rootQ] = rootP;size[rootP] += size[rootQ];} else {parent[rootP] = rootQ;size[rootQ] = size[rootP];}count--;}

完整算法

public class UnionFind {int count;int[] parent;int[] size;UnionFind(int N) {this.count = N;this.parent = new int[N];this.size = new int[N];for (int i = 0; i < N; ++i) {parent[i] = i;size[i] = 1;}}public void union(int p, int q) { // 连通 q, p分量int rootQ = find(q);int rootP = find(p);if (rootP == rootQ) {return;}if (size[rootP] > size[rootQ]) {parent[rootQ] = rootP;size[rootP] += size[rootQ];} else {parent[rootP] = rootQ;size[rootQ] = size[rootP];}count--;}private int find(int x) { // 获取x的父节点while (x != parent[x]) {parent[x] = parent[parent[x]];x = parent[x];}return x;}public boolean connected(int p, int q) { // 判断q p是否连通int rootQ = find(q);int rootP = find(p);return rootP == rootQ;}public int count() { // 获取联通分量个数return count;}
}

并查集 (Union-Find)算法相关推荐

  1. 关于 并查集(union find) 算法基本原理 以及 其 在分布式图场景的应用

    二月的最后一篇水文-想写一些有意思的东西. 文章目录 环检测在图数据结构中的应用 深度/广度优先 检测环 并查集数据结构 (Union-Find) 基本概念 初始化 合并 union 查找祖先 优化1 ...

  2. 基于并查集的kruskal算法

    #include <iostream> //并查集的kruskal算法using namespace std;const int max_ve=1005,max_ed=15005;int ...

  3. 亲戚关系关系算法java程序_C++并查集亲戚(Relations)算法实例

    本文实例讲述了C++并查集亲戚(Relations)算法.分享给大家供大家参考.具体分析如下: 题目: 亲戚(Relations) 或许你并不知道,你的某个朋友是你的亲戚.他可能是你的曾祖父的外公的女 ...

  4. 数据结构-PHP 并查集(Union Find)

    文章目录 数据结构-PHP 并查集(Union Find) 1.并查集示意图 2.并查集合并 3.并查集简单的代码示例 3.1 PHP代码定义 3.2 输出演示 数据结构-PHP 并查集(Union ...

  5. 数据结构与算法(十二)并查集(Union Find)及时间复杂度分析

    本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化 Quick Find Quick Union 基于size的优化 基于rank的优化 路径压缩优化 并查集的时间复杂度 并查集的 ...

  6. 并查集与贪心算法的应用之求解无向图的最小生成树

    一,介绍 本文介绍使用Kruskal算法求解无向图的最小生成树.Kruskal是一个贪心算法,并且使用了并查集这种数据结构. 关于并查集的介绍,参考:数据结构--并查集的原理及实现 二,构造一个无向图 ...

  7. 图 相关算法~从头学算法【广搜、 深搜、 拓扑排序、 并查集、 弗洛伊德算法、迪杰斯特拉算法】

    图的相关主流算法主要有: 广度优先搜索 深度优先搜索 拓扑排序 并查集 多源最短路径(弗洛伊德算法) 单源最短路径(迪杰斯特拉算法) 其中呢,最基本的是前两种,也就是平时常用的广搜和深搜,本文中将概要 ...

  8. 普林斯顿算法(1.3)并查集(union-find算法)——本质就是一个数 下面的子树代表了连在一起的点...

    转自:https://libhappy.com/2016/03/algs-1.3/ 假设在互联网中有两台计算机需要互相通信,那么该怎么确定它们之间是否已经连接起来还是需要架设新的线路连接这两台计算机. ...

  9. 九度OJ 1024 畅通工程 -- 并查集、贪心算法(最小生成树)

    题目地址:http://ac.jobdu.com/problem.php?pid=1024 题目描述: 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有 ...

  10. 经典算法-并查集、快速排序、字典序算法、二分搜索、牛顿开方法、求质数(筛选法)、编辑距离、滑动窗口、异或求重、长除法

    目录 ​​​​​​​​​​​​​​ 并查集 快速排序 字典序算法 二分搜索 开根号-牛顿开方法 求质数 编辑距离 滑动窗口 异或求重 长除法 ​​​​​​​ 并查集 并查集用于解决相同元素集合动态连接 ...

最新文章

  1. webgl坐标转换_WebGL 坐标系统
  2. C#抽象类与接口的区别【转】
  3. HALCON示例程序measure_metal_part_id.hdev使用xld边缘拟合检测零件加工是否合格
  4. CSS3 nth 伪类选择器
  5. 使用MOM 2005监视DC的磁盘空间
  6. 前嗅ForeSpider教程:创建模板
  7. nginx fastcgi python_webpy + nginx + fastcgi 构建python应用
  8. mysql如何创建用户代码_MySQl创建用户和授权的方法介绍(代码示例)
  9. dos2unix,unix2dos
  10. 面对对象三大特性之一继承性。
  11. 基于HBR的云上统一备份最佳实践
  12. 非常有意思的35句话
  13. React纯前端生成word文档(支持多图片导出)
  14. 【支付】商业银行作为收单机构的银行卡支付流程
  15. 计算机在微表情的应用,基于深度卷积神经网络的微表情识别
  16. 计算机应用word单元测试2,(计算机应用基本技能测试二.doc
  17. Failed to execute ‘getRangeAt‘ on ‘Selection‘: 0 is not a valid index.“报错
  18. AI上推荐 之 AFM与DIN模型(当推荐系统遇上了注意力机制)
  19. Linux系统命令行执行MySQL脚本
  20. Spark商业实战三部曲源码地址

热门文章

  1. django自定义模板标签,通过键获取字典的值,屏蔽姓名等隐蔽信息并调用展示到页面上
  2. pulsar配置文件常用配置项
  3. FastJson PropertyNamingStrategy 转换成JSON字符串的四种格式配置及源码解析
  4. python代码评测结果tle_TLE计算列表中指定范围内的元素数 - python
  5. c#把日期改成数字字符串_C#编写壹个函数将输入的中文日期转换为阿拉伯数字日期...
  6. HDOJ 2030-汉字统计
  7. oracle 052 题库更新,OCP题库升级,新版052考试题及答案整理-18
  8. dubbo指定服务提供者ip_使用指定IP调用Dubbo服务
  9. 从零开始学架构三 高性能
  10. PreparedStatement批量执行sql