【数据结构】高效解决连通性问题的并查集详解及Python实现

news2024/9/21 19:08:22

文章目录

    • 1. 并查集:一种高效的数据结构
    • 2. 并查集的基本操作与优化
      • 2.1 初始化
      • 2.2 查找操作与路径压缩
      • 2.3 合并操作与按秩合并
    • 3. 并查集的应用
      • 3.1 判断连通性
      • 3.2 计算连通分量
    • 4. 并查集的实际案例
      • 4.1 图的连通性问题
      • 4.2 网络连接问题
    • 5. 并查集的优缺点
      • 5.1 优点
      • 5.2 缺点
    • 6. 结论

1. 并查集:一种高效的数据结构

并查集(Union-Find)是一种用于处理不相交集合(Disjoint Sets)的数据结构。它支持两种操作:合并(Union)和查找(Find)。这种数据结构常用于解决连通性问题,如图论中的连通分量、网络中的连通子网等。

2. 并查集的基本操作与优化

2.1 初始化

并查集通过一个数组 parent 来表示每个元素的父节点,另一个数组 rank 用于优化合并操作。以下是初始化的代码:

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

uf = UnionFind(10)
print(uf.parent)
print(uf.rank)

2.2 查找操作与路径压缩

查找操作用于找到某个元素所在集合的根节点。路径压缩技术通过将访问过的节点直接连接到根节点上,从而降低树的高度,提高后续查找操作的效率。以下是路径压缩的实现代码:

def find(self, p):
    if self.parent[p] != p:
        self.parent[p] = self.find(self.parent[p])  # 路径压缩
    return self.parent[p]

2.3 合并操作与按秩合并

合并操作用于将两个不相交的集合合并为一个集合。按秩合并技术确保在合并操作中总是将高度较小的树连接到高度较大的树上,从而避免增加树的高度,按秩合并还可以看看这篇:并查集(按秩合并+路径压缩)基础讲解。以下是按秩合并的实现代码:

def union(self, p, q):
    rootP = self.find(p)
    rootQ = self.find(q)

    if rootP != rootQ:
        if self.rank[rootP] < self.rank[rootQ]:
            rootP, rootQ = rootQ, rootP  # 确保rootP是秩较高的树根
        self.parent[rootQ] = rootP
        if self.rank[rootP] == self.rank[rootQ]:
            self.rank[rootP] += 1  # 更新秩

3. 并查集的应用

3.1 判断连通性

并查集可以用于判断两个节点是否连通。通过检查它们的根节点是否相同即可判断。

def connected(self, p, q):
    return self.find(p) == self.find(q)

uf = UnionFind(10)
uf.union(1, 2)
uf.union(2, 3)
print(uf.connected(1, 3))  # 输出: True
print(uf.connected(1, 4))  # 输出: False

3.2 计算连通分量

并查集还可以用于计算连通分量的数量。在初始状态下,每个节点都是一个独立的连通分量,随着合并操作的进行,连通分量的数量逐渐减少。

def count_components(self):
    root_set = set()
    for i in range(len(self.parent)):
        root_set.add(self.find(i))
    return len(root_set)

uf = UnionFind(10)
uf.union(1, 2)
uf.union(2, 3)
print(uf.count_components())  # 输出: 8

4. 并查集的实际案例

4.1 图的连通性问题

在图论中,可以用并查集解决连通分量、最小生成树等问题。例如,Kruskal算法用于寻找最小生成树,通过并查集来判断边的两个端点是否属于同一连通分量,从而避免形成环。

def kruskal(edges, n):
    edges.sort(key=lambda x: x[2])
    uf = UnionFind(n)
    mst = []
    total_weight = 0

    for u, v, weight in edges:
        if not uf.connected(u, v):
            uf.union(u, v)
            mst.append((u, v, weight))
            total_weight += weight

    return mst, total_weight

edges = [(0, 1, 1), (0, 2, 4), (1, 2, 2), (1, 3, 5), (2, 3, 3)]
n = 4
mst, total_weight = kruskal(edges, n)
print("最小生成树:", mst)
print("总权重:", total_weight)

4.2 网络连接问题

并查集可以用于解决网络连接问题,例如判断网络中两个计算机是否连通,以及在动态变化的网络中维护连通性信息。

class Network:
    def __init__(self, n):
        self.uf = UnionFind(n)

    def connect(self, p, q):
        self.uf.union(p, q)

    def is_connected(self, p, q):
        return self.uf.connected(p, q)

network = Network(5)
network.connect(0, 1)
network.connect(1, 2)
print(network.is_connected(0, 2))  # 输出: True
print(network.is_connected(0, 3))  # 输出: False

5. 并查集的优缺点

5.1 优点

  1. 高效:并查集的合并和查找操作都具有接近常数时间的复杂度,尤其是在使用路径压缩和按秩合并优化后。
  2. 简单:并查集的实现相对简单,代码量少,容易理解和维护。
  3. 实用:并查集在图论、网络等领域有广泛的应用,可以有效解决连通性问题。

5.2 缺点

  1. 适用范围有限:并查集主要适用于连通性问题,对其他类型的问题不适用。
  2. 静态结构:并查集对动态变化的集合处理较为困难,例如频繁的插入和删除操作。

6. 结论

并查集是一种简单高效的数据结构,广泛应用于图论、网络连通性等问题。通过路径压缩和按秩合并技术,可以显著提升操作效率。在解决连通性问题时,并查集是一个强大的工具。

通过本文的介绍和示例代码,希望能够帮助读者理解并查集的原理和应用。如果在实际项目中遇到连通性问题,尝试使用并查集,可能会带来意想不到的效果。


在这里插入图片描述

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

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

相关文章

哪些网站是获取独立站外链的最佳选择?

想要为独立站获取外链&#xff0c;有几个地方可以考虑&#xff0c;首先自然是最有效的博客和文章投稿网站&#xff0c;找那些与你的行业相关的博客和内容平台&#xff0c;撰写高质量的文章&#xff0c;里面自然地嵌入你的链接。这是最有价值的外链 然后不分其他&#xff0c;效…

ESP32-S3多模态交互方案在线AI语音设备应用,启明云端乐鑫代理商

随着物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;嵌入式设备正逐渐变得智能化&#xff0c;让我们的家庭生活变得更加智能化和个性化。 随着大型语言模型的不断进步和优化&#xff0c;AI语音机器人设备能够实现更加智能、…

超越 Transformer开启高效开放语言模型的新篇章

在人工智能快速发展的今天&#xff0c;对于高效且性能卓越的语言模型的追求&#xff0c;促使谷歌DeepMind团队开发出了RecurrentGemma这一突破性模型。这款新型模型在论文《RecurrentGemma&#xff1a;超越Transformers的高效开放语言模型》中得到了详细介绍&#xff0c;它通过…

软件工程课设——成绩管理系统

软件工程课设——成绩管理系统 该文档是软件工程课程设计&#xff0c;成绩管理子系统的开发模块仓库。 功能分析 从面向的用户分&#xff0c;成绩管理子系统主要面向三类用户&#xff0c;即至少需要满足这三类用户的需求&#xff1a; 学生&#xff1a;学生是成绩管理系统的…

实现keepalive+Haproxyde 的高可用

需要准备五台实验机 一台客户机&#xff1a;test1 两台&#xff1a;一主一备的实验机&#xff1a;test2 test3 两台真实服务器&#xff1a;nginx1 nginx2 实验 首先在两台实验机上安装Haproxy 安装依赖环境&#xff0c;并将Haproxy的包进行解压处理 yum install -y pcre…

什么ISP?什么是IAP?

做单片机开发的工程师经常会听到两个词&#xff1a;ISP和IAP&#xff0c;但新手往往对这两个概念不是很清楚&#xff0c;今天就来和大家聊聊什么是ISP&#xff0c;什么是IAP&#xff1f; 一、ISP ISP的全称是&#xff1a;In System Programming&#xff0c;即在系统编程&…

vscode常用组件

1.vue-helper 启用后点击右下角注册&#xff0c;可以通过vue组件点击到源码里面 2.【Auto Close Tag】和【Auto Rename Tag】 3.setting---Auto Reveal Exclude vscode跳转node_modules下文件&#xff0c;没有切换定位到左侧菜单目录> 打开VSCode的setting配置&#xff…

Redis的使用(四)常见使用场景-缓存使用技巧

1.绪论 redis本质上就是一个缓存框架&#xff0c;所以我们需要研究如何使用redis来缓存数据&#xff0c;并且如何解决缓存中的常见问题&#xff0c;缓存穿透&#xff0c;缓存击穿&#xff0c;缓存雪崩&#xff0c;以及如何来解决缓存一致性问题。 2.缓存的优缺点 2.1 缓存的…

Transformer模型解析:走进自然语言处理的新时代

UPDATED&#xff1a;2023 年 1 月 27 日&#xff0c;本文登上 ATA 头条。&#xff08;注&#xff1a;ATA 全称 Alibaba Technology Associate&#xff0c;是阿里集团最大的技术社区&#xff09;UPDATED&#xff1a;2023 年 2 月 2 日&#xff0c;本文在 ATA 获得鲁肃点赞。&…

华为OD算法题汇总

60、计算网络信号 题目 网络信号经过传递会逐层衰减&#xff0c;且遇到阻隔物无法直接穿透&#xff0c;在此情况下需要计算某个位置的网络信号值。注意:网络信号可以绕过阻隔物 array[m][n]&#xff0c;二维数组代表网格地图 array[i][j]0&#xff0c;代表i行j列是空旷位置 a…

数据结构(4.0)——串的定义和基本操作

串的定义(逻辑结构) 串&#xff0c;即字符串(String)是由零个或多个字符组成的有序数列。 一般记为Sa1a2....an(n>0) 其中&#xff0c;S是串名&#xff0c;单引号括起来的字符序列是串的值;ai可以是字母、数字或其他字符&#xff1b;串中字符的个数n称为串的长度。n0时的…

分布式对象存储minio

本教程minio 版本&#xff1a;RELEASE.2021-07-*及以上 1. 分布式文件系统应用场景 互联网海量非结构化数据的存储需求 电商网站&#xff1a;海量商品图片视频网站&#xff1a;海量视频文件网盘 : 海量文件社交网站&#xff1a;海量图片 1.1 Minio介绍 MinIO 是一个基于Ap…

Spring解决循环依赖:三级缓存

1.什么是循环依赖 通俗来讲&#xff0c;循环依赖指的是一个实例或多个实例存在相互依赖的关系&#xff08;类之间循环嵌套引用&#xff09;。 2.Spring如何解决循环依赖 首先&#xff0c;先介绍Spring是如何创建Bean的。 &#xff08;1&#xff09;createBeanInstance&…

【LoadRunner】博客笔记项目 性能测试报告

文章目录 前言一、博客笔记项目性能测试介绍二、编写性能测试脚本&#xff08;VUG&#xff09; 2.1 测试脚本编写步骤 2.2 脚本总代码和结果分析三、创建测试场景&#xff08;Controller&#xff09; 3.1 测试场景创建实现步骤四、生成测试报告&#xff08;Anal…

集合相关知识

string final&#xff0c;不能追加&#xff0c;需要重新new一个 stringbuild&#xff0c;内容 可变&#xff0c;可以重新赋能&#xff0c;能够追加&#xff0c;空间不足创造一个更大的&#xff0c;然后复制过去 stringbufferbuild 线程安全 javac编译&#xff0c;字符串加号…

SpringBoot介绍以及第一个SpringBoot程序

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 文章目录 2.第一个SpringBoot程序2.1Spring Boot介绍2.2使用idea创建Spring Boot程序2.2.1 社区版idea2.2.2专业版idea2.2.3创建SpringBoot项目2.2.4项目代码和目录介绍目录介绍pom文件 2.3Web…

Linux 上 TTY 的起源

注&#xff1a;机翻&#xff0c;未校对。 What is a TTY on Linux? (and How to Use the tty Command) What does the tty command do? It prints the name of the terminal you’re using. TTY stands for “teletypewriter.” What’s the story behind the name of the co…

【边缘计算网关教程】6.松下 Mewtocol TCP 协议

前景回顾&#xff1a;【边缘计算网关教程】5.三菱FX3U编程口通讯-CSDN博客 松下 Mewtocol TCP 协议 适配PLC&#xff1a;松下FP0H 松下XHC60ET 1. 硬件连接 Mewtocol TCP协议采用网口通信的方式&#xff0c;因此&#xff0c;只需要保证网关的LAN口和松下PLC的IP在一个网段即…

STM32怎么把VDD与VSS引脚配置为GPIO?

在 STM32 微控制器中&#xff0c;VDD 和 VSS 引脚是供电引脚&#xff0c;分别用于电源和接地。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕设800套和语言类教学&#xff0c;敲个…

使用base64通用文件上传

编写一个上传文件的组件 tuku,点击图片上传后使用FileReader异步读取文件的内容&#xff0c;读取完成后获得文件名和base64码&#xff0c;调用后端uploadApi,传入姓名和base64文件信息&#xff0c;后端存入nginx中&#xff0c;用于访问 tuku.ts组件代码&#xff1a; <templa…