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

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.mzph.cn/news/830496.shtml

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

相关文章

分布式存储 Ceph 的演进经验

从 2004 年到今天&#xff0c;Ceph 的存储后端一直都在演变&#xff0c;从最开始基于 B 树的 EBOFS 演变到今天的 BlueStore&#xff0c;存储后端已经变得非常成熟&#xff0c;新的存储系统不仅能够提供良好的性能&#xff0c;还有着优异的兼容性。我们在这篇文章中将要简单介绍…

Android SQLiteDatabase的使用详解

1、数据库–公共变量&#xff1a; 2、数据库–打开&#xff1a; 3、数据库–增&#xff1a; 4、数据库–删&#xff1a; 5、数据库–改&#xff1a; 6、数据库–查&#xff1a; 7、数据库–关闭&#xff1a; 8、数据库–辅助工具&#xff1a; 9、数据库–效果&…

配置DHCP和DNS

DHCP DHCP原理 作用&#xff1a;是一种网络协议&#xff0c;用于自动分配IP地址、子网掩码、默认网关、DNS服务器等TCP/IP参数 1.DHCP的四个报文 1.discover报文&#xff1a; 找寻dhcp服务器 2.offer报文&#xff1a; 服务器回复discover报文并且携带网络配置信息&#xff…

我在公司干了两年,有个在公司工作三年的成员要离职,接手别人代码才发现真的是一言难尽

微服务框架是别的团队的人搭建的&#xff0c;他负责单独开发一个报表模块&#xff0c;这是初始版本&#xff0c;还未上线 1、nacos做注册中心&#xff0c;却胡乱注册&#xff0c;服务命名有下划线 测试环境nacos配置命名空间为dev&#xff0c;直接与其他的微服务test命名空间…

Qt QLineEdit详解

1.简介 QLineEdit是一个单行文本编辑器。 行编辑允许用户使用一组有用的编辑功能输入和编辑单行纯文本&#xff0c;包括撤消和重做、剪切和粘贴以及拖放。 通过更改行编辑的echoMode&#xff0c;它也可以用作“只写”字段&#xff0c;用于密码等输入。 文本的长度可以限制为ma…

毅四捕Go设计模式笔记——命令模式

命令模式&#xff08;Command Pattern&#xff09; 为了解决什么问题&#xff1f; 命令模式的目的是将请求发起者和请求执行者解耦&#xff0c;使得请求的发起者不需要知道具体的执行者是谁&#xff0c;也不需要知道执行的具体过程&#xff0c;只需要发送请求即可。 通过使用…

如何轻松在D盘新建文件夹?意外丢失的文件夹怎么找回

对于很多刚接触电脑的朋友来说&#xff0c;如何正确地新建文件夹并将其放置在特定盘符&#xff08;如D盘&#xff09;可能是一个不小的挑战。同时&#xff0c;如果新建的文件夹突然消失&#xff0c;而我们又确信自己没有删除它&#xff0c;那么该如何找回呢&#xff1f;本文将为…

直播间怎么提高流量?巨量千川官方真实投流助力获客轻松翻倍

随着互联网的快速发展&#xff0c;直播已经成为了一种极具吸引力和互动性的娱乐和营销方式。然而&#xff0c;如何提高直播间的流量&#xff0c;(直播间流量&#xff1a;kxs7667)吸引更多观众成为了每个直播主都关注的重要问题。与此同时&#xff0c;巨量千川官方真实投流作为一…

如何在WordPress中设置网站的SEO标题和描述

在WordPress中&#xff0c;想要让你的网站在搜索引擎结果中脱颖而出&#xff0c;设置优秀的SEO标题和描述至关重要。这不仅可以帮助搜索引擎更好地理解你的网站内容&#xff0c;还可以吸引更多的点击率和流量。而选择一款合适的SEO插件是实现这一目标的关键之一。让我们来看看两…

pgvector扩展在IvorySQL Oracle兼容模式下的应用实践

向量数据库是生成式人工智能(GenAI)的关键组成部分。作为PostgreSQL的重要扩展&#xff0c;pgvector支持高达16000维的向量计算能力&#xff0c;使得PostgreSQL能够直接转化为高效的向量数据库。 IvorySQL基于PostgreSQL开发&#xff0c;因此它同样支持添加pgvector扩展。在Ora…

部署YUM仓库及NFS共享服务

YUM yum仓库常用类型&#xff1a; 本地源仓库&#xff1a;baserulfile:// 在线源仓库&#xff1a;baserulhttp:// ftp源仓库&#xff1a;baseru&#xff1a;ftp&#xff1a;// 实验&#xff1a; 首先安装软件 [rootlocalhost yum.repos.d]# cd /mnt/Packages/ [rootloca…

基于FPGA的数字信号处理(3)--什么是浮点数?

科学计数法 你可能不了解「浮点数」&#xff0c;但你一定了解「科学记数法」。 10进制科学记数法把一个数表示成a与10的n次幂相乘的形式&#xff08;1≤|a|<10&#xff0c;a不为分数形式&#xff0c;n为整数&#xff09;&#xff0c;例如&#xff1a; 19970000000000 1.9…

2024-04学习笔记

1.sql优化-子查询改为外连接 1.改之前 改之前是这样&#xff0c;那针对查出来的每一条数据&#xff0c;都要执行一次箭头所指的函数 执行的sql很慢 2.改之后 改之后是这样&#xff0c;整体做外连接&#xff0c;不用每一条都再执行一次查询 执行时间缩短了好几倍 2.Mybatis中…

Mysql基础(四)DML之insert语句

一 insert 语句 强调&#xff1a; 本文介绍的内容很基础,仅做记录用,参考价值较少 ① 总述 目的&#xff1a; 增加rows记录1、完整格式insert [into] 表名[字段名1[, 字段名2]] value[s](值1, 值2);备注&#xff1a;指定部分字段添加,没有被指定的字段要么会自动增长,要…

MySQL中SELECT语句的执行过程

2.1.1. 一条SELECT语句的执行过程 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层 Server层负责建立连接、分析和执行SQL存储引擎层负责数据的存储和提取&#xff0c;支持 InnoDB、MyISAM、Memory 等多个存储引擎&#xff0c;MySQL5.5以后默认使用InnoDB&#xff0…

Nacos、OpenFeign、网关 笔记

一、远程调用 1.1配置RestTemplate配置类 package com.hmall.cart.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate;Configuration public c…

【06016传感器原理与应用】第3章 力学量传感器 期末复习自考复习

第3章 力学量传感器 定义&#xff1a;将力/压力等力学量信号变成电信号的装置 称为力学量传感器。 力学传感器的分类&#xff1a; 应用普遍的&#xff1a;电阻式、压电式、电容式、电感式、谐振式、变磁阻式、光纤式等等。传统的如弹簧&#xff1a;成本低、不需电源&#xff…

Docker-compose的介绍与用法

Docker-compose Docker Compose 是一个开源的容器编排工具&#xff0c;由 Docker 官方开发。它允许开发者定义一个或多个 Docker 容器作为单个服务&#xff0c;并将这些服务组合成一个项目。这些定义被保存在一个 YAML 文件中&#xff0c;称为 docker-compose.yml。 使用 Dock…

C#命名空间常用函数

在C#中&#xff0c;不同命名空间下有各种常用函数&#xff0c;下面列举一些常见的函数及其对应的命名空间&#xff1a; System命名空间&#xff1a; Console.WriteLine()&#xff1a;用于向控制台输出信息。Convert.ToInt32()&#xff1a;用于将其他数据类型转换为整数类型。 S…

个人图床解决方案(PicGo+对象存储, 几乎免费)

个人图床解决方案(PicGo对象存储) 原先我的解决方案是github做图床,套一层Cloudflare的cdn来加速国内访问, 但国内访问仍然过慢, 特别是一些图很多的文章, 加载非常慢. 所以我想着改善一下, 在对比了一些解决方案之后, 我选择了PicGo缤纷云搭建主图床, 部分图片放在 去不图床,…