【算法基础实验】图论-UnionFind连通性检测之quick-find

news2024/12/28 3:20:43

Union-Find连通性检测之quick-find

理论基础

在图论和计算机科学中,Union-Find 或并查集是一种用于处理一组元素分成的多个不相交集合(即连通分量)的情况,并能快速回答这组元素中任意两个元素是否在同一集合中的问题。Union-Find 特别适用于连通性问题,例如网络连接问题或确定图的连通分量。

Union-Find 的基本操作

Union-Find 数据结构支持两种基本操作:

  1. Union(合并): 将两个元素所在的集合合并成一个集合。
  2. Find(查找): 确定某个元素属于哪个集合,这通常涉及找到该集合的“代表元素”或“根元素”。

Union-Find 的结构

Union-Find 通常使用一个整数数组来表示,其中每个元素的值指向它的父节点,这样形成了一种树形结构。集合的“根元素”是其自己的父节点。

Union-Find 的优化技术

为了提高效率,Union-Find 实现中常用两种技术:

  1. 路径压缩(Path Compression): 在执行“查找”操作时,使路径上的每个节点都直接连接到根节点,从而压缩查找路径,减少后续操作的时间。
  2. 按秩合并(Union by Rank): 在执行“合并”操作时,总是将较小的树连接到较大的树的根节点上。这里的“秩”可以是树的深度或者树的大小。

应用示例

Union-Find 算法常用于处理动态连通性问题,如网络中的连接/断开问题或者图中连通分量的确定。例如,Kruskal 的最小生成树算法就使用 Union-Find 来选择边,以确保不形成环路。

总结

Union-Find 是解决连通性问题的一种非常高效的数据结构。它能够快速合并集合并快速判断元素之间的连通性。通过路径压缩和按秩合并的优化,Union-Find 在实际应用中可以接近常数时间完成操作。因此,它在算法竞赛、网络连接和社交网络分析等领域有广泛的应用。

数据结构

private int[] id // 分量id(以触点作为索引)
private int count // 分量数量

实验数据和算法流程

本实验使用tinyUF.txt作为实验数据,数据内容如下,一共定义了10对连通性关系

10
4 3
3 8
6 5
9 4
2 1
8 9
5 0
7 2
6 1
1 0
6 7

实验的目的是检测数据中共有多少个连通分量,并打印每个元素所属的连通分量编号
下图是处理元素5和9的一个处理瞬间

请添加图片描述

完整流程如下
请添加图片描述

代码实现

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdIn;

public class myQuickFind
{
    private int[] id; // 分量id(以触点作为索引)
    private int count; // 分量数量
    public myQuickFind(int N)
    { // 初始化分量id数组
        count = N;
        id = new int[N];
        for (int i = 0; i < N; i++)
            id[i] = i;
    }
    public int count()
    { return count; }
    public boolean connected(int p, int q)
    { return find(p) == find(q); }

    public int find(int p)
    { return id[p]; }

    public void union(int p, int q)
    { // 将p和q归并到相同的分量中
        int pID = find(p);
        int qID = find(q);
        // 如果p和q已经在相同的分量之中则不需要采取任何行动
        if (pID == qID) return;
        // 将p的分量重命名为q的名称
        for (int i = 0; i < id.length; i++)
            if (id[i] == pID) id[i] = qID;
        count--;
    }

    public static void main(String[] args)
    { // 解决由StdIn得到的动态连通性问题
        int N = StdIn.readInt(); // 读取触点数量
        myQuickFind qf = new myQuickFind(N); // 初始化N个分量
        while (!StdIn.isEmpty())
        {
            int p = StdIn.readInt();
            int q = StdIn.readInt(); // 读取整数对
            if (qf.connected(p, q)) continue; // 如果已经连通则忽略
            qf.union(p, q); // 归并分量
        }
        StdOut.println(qf.count() + " components");
        for(int i = 0;i<N;i++){
            StdOut.println(i + ":"+qf.find(i));
        }
    }
}

代码详解

这段代码实现了一种名为 Quick-Find 的并查集算法,用来解决动态连通性问题。下面是详细的代码解读:

类定义和变量


public class myQuickFind {
    private int[] id; // 分量id(以触点作为索引)
    private int count; // 分量数量

  • id 数组用来存储每个节点的分量标识。在 Quick-Find 中,id 数组的每个位置的值表示那个位置所属的组。
  • count 记录当前图中连通分量的数量。

构造函数


public myQuickFind(int N) {
    count = N;
    id = new int[N];
    for (int i = 0; i < N; i++)
        id[i] = i;
}

构造函数接受一个整数 N,表示图中节点的数量。初始时,每个节点自成一个连通分量,即每个节点都是自己的代表,因此 id[i] 初始化为 i

辅助方法


public int count() { return count; }
public boolean connected(int p, int q) { return find(p) == find(q); }
public int find(int p) { return id[p]; }

  • count() 返回当前连通分量的数量。
  • connected(p, q) 检查两个节点是否属于同一个连通分量。
  • find(p) 查找节点 p 的连通分量标识。

Union 操作


public void union(int p, int q) {
    int pID = find(p);
    int qID = find(q);
    if (pID == qID) return; // 如果p和q已经在相同的分量之中则不需要采取任何行动
    for (int i = 0; i < id.length; i++)
        if (id[i] == pID) id[i] = qID;
    count--;
}

union(p, q) 方法用于合并包含节点 pq 的两个连通分量。如果两者已经在同一个连通分量中,则不做任何操作。否则,遍历 id 数组,将所有属于 p 的连通分量的节点都重新标记为属于 q 的连通分量。

主函数


public static void main(String[] args) {
    int N = StdIn.readInt(); // 读取触点数量
    myQuickFind qf = new myQuickFind(N); // 初始化N个分量
    while (!StdIn.isEmpty()) {
        int p = StdIn.readInt();
        int q = StdIn.readInt(); // 读取整数对
        if (qf.connected(p, q)) continue; // 如果已经连通则忽略
        qf.union(p, q); // 归并分量
    }
    StdOut.println(qf.count() + " components");
    for(int i = 0;i<N;i++){
        StdOut.println(i + ":"+qf.find(i));
    }
}

主函数从标准输入读取节点数量和一系列整数对。对于每对整数,如果它们不属于同一个连通分量,则调用 union 方法将它们合并。程序的最终输出是图中的连通分量数量,以及每个节点的连通分量标识。

Quick-Find 的性能

Quick-Find 算法的缺点在于 union 操作的高成本,它需要 O(N) 时间来处理每次合并操作,这在处理大量操作时可能变得非常慢。尽管如此,它的 find 操作非常快,只需常数时间 O(1)。因此,这种数据结构适用于不频繁进行 union 操作但需要频繁进行连通性检查的场景。

实验

代码编译

javac myQuickFind.java

代码运行

java myQuickFind < ..\data\tinyUF.txt 
2 components
0:1
1:1
2:1
3:8
4:8
5:1
6:1
7:1
8:8
9:8

参考资料

算法(第四版) 人民邮电出版社

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1627552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RDD编程初级实践

参考链接 spark入门实战系列--8MLlib spark 实战_mob6454cc68310b的技术博客_51CTO博客https://blog.51cto.com/u_16099212/7454034 Spark和Hadoop的安装-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/138021948?spm1001.2014.3001.5501 1. spark-shell…

Linux的学习之路:22、线程(2)

摘要 本章继续讲一下线程的东西 目录 摘要 一、抢票 二、加锁保护 三、死锁 1、死锁四个必要条件 2、避免死锁 四、同步 1、常见的线程安全的情况 2、常见不可重入的情况 3、常见可重入的情况 4、可重入与线程安全联系 5、可重入与线程安全区别 一、抢票 这里回…

大模型咨询培训老师叶梓:利用知识图谱和Llama-Index增强大模型应用

大模型&#xff08;LLMs&#xff09;在自然语言处理领域取得了显著成就&#xff0c;但它们有时会产生不准确或不一致的信息&#xff0c;这种现象被称为“幻觉”。为了提高LLMs的准确性和可靠性&#xff0c;可以借助外部知识源&#xff0c;如知识图谱。那么我们如何通过Llama-In…

clickhouse与oracle传输数据

参考 https://github.com/ClickHouse/clickhouse-jdbc-bridge https://github.com/ClickHouse/clickhouse-jdbc-bridge/blob/master/docker/README.md clickhouse官方提供了一种方式&#xff0c;可以实现clickhouse与oracle之间传输数据&#xff0c;不仅仅是oracle&#xff0…

Java后端利用百度地图全球逆地理编码,获取地址

声明&#xff1a;本人是在实习项目的时候遇到的问题 一.使用Api分为四步骤全球逆地理编码 rgc 反geo检索 | 百度地图API SDK 步骤1,2自行完成 接下来去获取AK 二.申请AK 登录百度账号 点击创建应用&#xff0c;选择自己想用的服务&#xff0c;我只单选了逆地理编码&#xff…

debian gnome-desktop GUI(图形用户界面)系统

目录 &#x1f31e;更新 &#x1f3a8;安装 &#x1f34e;分配 &#x1f6cb;️重启 &#x1f511;通过VNC连接 debian gnome-desktop &#x1f31e;更新 sudo apt update sudo apt -y upgrade &#x1f3a8;安装 sudo apt -y install task-gnome-desktop 这个过程比…

企业应该如何处理云安全问题。

企业甚至云提供商配置错误的云基础设施可能会导致多个漏洞&#xff0c;从而显着增加组织的攻击面。德迅云安全通过帮助企业和部署云安全的核心组件来解决这些问题。其中包括全面的安全态势、持续优化的策略、全周期风险管理、流量监控、威胁响应、风险缓解和数字资产管理。 云安…

力扣-有效的数独

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 注…

codePen按钮样式学习

前言 看到codepen里面有的按钮搞得很炫酷&#xff0c;但其实也不是很难&#xff0c;就学习记录一下 逐渐出现边框 大体上来说就是当鼠标悬浮的时候触发四个transition&#xff0c;用after、before和span的after和before四个伪类做hover出来的边框 <div class"btn bt…

笔记本硬盘坏了怎么把数据弄出来 笔记本硬盘数据恢复一般需要多少钱

现在办公基本都离不开笔记本电脑&#xff0c;就连学生写作业也大多是都在电脑上完成。硬盘作为电脑存储的重要组成部分&#xff0c;承载着存储文件和各类软件的重任。如果硬盘出现故障&#xff0c;基本上这台电脑就无法正常工作&#xff0c;同时我们可能面临丢失很多重要的数据…

设计不外流,保护创意的同时锁住图纸安全!

在设计行业中&#xff0c;图纸和创意文稿的安全至关重要&#xff0c;因为它们体现了企业的创新能力和核心竞争力。华企盾DSC数据防泄密系统提供了一系列功能&#xff0c;可以有效地保护这些珍贵的设计和文档不被外泄。以下是如何利用华企盾DSC系统保障设计图纸安全的关键措施&a…

JavaScript算法描述【排序与搜索】六大经典排序|合并两个有序数组|第一个错误的版本

&#x1f427;主页详情&#xff1a;Choice~的个人主页 &#x1f4e2;作者简介&#xff1a;&#x1f3c5;物联网领域创作者&#x1f3c5; and &#x1f3c5;阿里专家博主&#x1f3c5; and &#x1f3c5;华为云享专家&#x1f3c5; ✍️人生格言&#xff1a;最慢的步伐不是跬步&…

进销存单机版和excel进销存那个好用

进销存单机版和EXCEL进销存哪个好用&#xff1f;单机版是安装在单台电脑上使用的&#xff0c;它不能像网络版一样可以多台电脑同时共享数据&#xff0c;所以进销存单机版有一个优势就是不需要连接网络也可以使用。 进销存单机版 进销存软件单机版是经过开发人员设计好的一种信…

游戏新手村21:再谈游戏广告页面设计

前文我们说到了网页游戏的LandingPage页面设计中需要遵循的一些规范和注意事项&#xff0c;本章我们重点谈下网络游戏的广告页面设计。 之前在金山的时候&#xff0c;大家习惯或者喜欢称LandingPage为分流页&#xff0c;这个页面需要加入哪些游戏信息才能在短时间内俘获玩家的…

【办公类-22-14】周计划系列(5-6)“周计划-06 19周的周计划教案合并打印PDF(最终打印版))

背景需求&#xff1a; 花了十周&#xff0c;终于把周计划教案的文字都写满、加粗、节日替换了。为了便于打印&#xff0c;我把19周的周计划教案全部合并在一起PDF。制作打印用PDF 思路 1、周计划是单独打印一张&#xff0c;因此要在第2页插入空白页&#xff0c; 2、教案有3页…

vue项目中基于fabric 插件实现涂鸦画布功能

vue项目中基于fabric 插件实现涂鸦画布功能 一、效果图二、安装依赖三、main.js引入四、主要代码 一、效果图 二、安装依赖 npm install fabric 三、main.js引入 import fabric from fabric Vue.use(fabric);四、主要代码 //封装成了一个组件 <template><el-dialogt…

atlas 500容器(ubuntu20.04)搭建

1.docker 及环境搭建略 2.宿主机驱动安装略 3.宿主机中能正确使用npu-smi 4.docker 拉取略 5.docker 容器启动 docker run -itd --device/dev/davinci0 --device/dev/davinci_manager --device/dev/devmm_svm --device/dev/hisi_hdc -v /run/board_cfg.ini:/run/b…

springboot如何使用RedisTemplate

第一步&#xff1a;创建一个spring boot项目 第二步&#xff1a;pom导入redis相关依赖 <!--reids依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </depen…

swagger xss漏洞复现

swagger xss漏洞复现 文章目录 swagger xss漏洞复现漏洞介绍影响版本实现原理漏洞复现修复建议: 漏洞介绍 Swagger UI 有一个有趣的功能&#xff0c;允许您提供 API 规范的 URL - 一个 yaml 或 json 文件&#xff0c;将被获取并显示给用户 根本原因非常简单 - 一个过时的库Dom…

「51媒体」城市推介会,地方旅游推荐,怎么做好媒体宣传

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 城市推介会和地方旅游推荐是城市形象宣传的重要组成部分&#xff0c;通过有效的媒体宣传可以提升城市的知名度和吸引力。&#xff1a; 一&#xff0c;活动内容层面&#xff1a; 突出亮点…