当前位置: 首页 > news >正文

【数据结构】[特殊字符] 并查集优化全解:从链式退化到近O(1)的性能飞跃 | 路径压缩与合并策略深度实战

并查集的优化

  • 导读
  • 一、合并优化
    • 1.1 基本原理
    • 1.2 按大小合并
    • 1.3 按秩合并
    • 1.4 两种合并的区别
      • **1.4.1 核心目标**
      • **1.4.2 数据存储**
      • **1.4.3 合并逻辑**
      • **1.4.4 树高控制**
      • **1.4.5 适用场景**
      • **1.4.6 路径压缩兼容性**
      • **1.4.7 极端案例对比**
      • **1.4.8 小结**
  • 二、查找优化
    • 2.1 路径压缩
    • 2.2 算法实现
  • 三、算法评估
    • 3.1**时间复杂度**
      • 3.1.1 **按大小合并(Union by Size)**
      • 3.1.2 **按秩合并(Union by Rank)**
      • 3.1.3 **路径压缩(Path Compression)**
    • 3.2 **空间复杂度**
      • 3.2.1 **按大小合并**
      • 3.2.2 **按秩合并**
      • 3.2.3 **路径压缩**
    • 3.3 **优化策略的协同作用**
      • 3.3.1 **按大小合并 + 路径压缩**
      • 3.3.2 **按秩合并 + 路径压缩**
    • 3.4 **极端场景示例**
      • 3.4.1 **按大小合并**
      • 3.4.2 **按秩合并**
    • 3.5 小结
  • 🚀 结语:并查集优化——效率与智慧的结晶
    • 🔍 **核心优化回顾**
    • ⏱️ **时间复杂度突破**
    • 🧩 **优化策略对比与选择**
    • 💡 **实战启示**
    • 🌟 **下篇预告**

并查集的优化

导读

大家好,很高兴又和大家见面啦!!!

在上一篇内容中我们正确认识了并查集,并通过数据元素与其双亲指针的映射关系实现了并查集的查找与合并的。

但是上一篇的算法实现中,算法的最坏时间复杂度可以达到 O ( N ) O(N) O(N),这并不能很好的满足高效处理动态连通性问题。

在今天的内容中,我们将通过路径优化与按秩合并两种优化方式对并查集实现进一步的优化,大大提高处理动态连通性的效率。

一、合并优化

在并查集中,影响其时间复杂度的操作在查找上,而树的高度h是影响查找时间复杂度的重要因素。那么我们要对并查集的算法进行优化,那就得从树高下手。

下面我们就来看一下如何通过优化不同子集的合并从而优化整个并查集的算法。

1.1 基本原理

当两个树高不同的子集进行合并时,会存在两种合并方案:

  • 小树合并到大树
  • 大树合并到小树

合并优化
不难发现,当大树将小树合并时并不会影响大树的树高,但是当小树将大树合并时,则会增加树高。

试想一下,如果我们要完成n棵树的合并,如果将n-1棵小树合并到大树上,这样我们就能保证在进行查找时,能够尽可能的降低查找时间复杂度。

但是当我们在进行合并时,是将大树合并到小树上,则会不断地增加树高,这样每一次合并,都会增加查找的时间复杂度。

因此为了尽可能优化并查集,那么我们在进行合并操作时,应该在每一次合并操作时,都保证是小树合并到大树上。

今天我们介绍两种优化方案——按大小合并、按秩合并。

1.2 按大小合并

按大小合并指的是根据树的大小,将小树合并到大树。

树的大小由树的结点数量决定,结点多的树为大树,结点少的树为小数。通过树的根结点的绝对值表示树的大小。

这里我们以大写字符为例,我们通过一个整型数组parent来存放每个元素的双亲位置信息:

按大小合并

该算法的实现比较简单,我们只需要在合并算法中加入一个对根结点大小的判断,并且在完成合并后,修改根结点的值:

//按大小合并优化
void Union_by_Size(DSU* s, int root1, int root2) {
   
	if (root1 != root2) {
   
		//根结点为负数,值越大,结点数量越少
		if (s->parent[root1] > s->parent[root2]) {
   
			s->parent[root2] += s->parent[root1];//修改大树根结点
			s->parent[root1] = root2;//修改小树根结点
		}
		else {
   
			s->parent[root1] += s->parent[root2];
			s->parent[root2] = root1;
		}
	}
}

通过按大小合并的方式优化,可以极大可能的降低合并后的树高,但是也不一定。

比如结点多但高度低的大树与结点少但高度高的小树进行合并,此时如果按照大小来进行合并,则会增加合并后树的高度。

那有没有不会影响高度的优化方式呢?这就是我们接下来要介绍的按秩合并;

1.3 按秩合并

所谓的秩(Rank)代表的是树合并前的最大高度。

按秩合并实际上就是根据树高进行合并,将矮树合并到高树中,从而确保在完成合并后的树高最小。

合并的规则如下:

  • 所有结点的初始高度为0,即根结点的高度为0
  • 将秩小的树合并到秩大的树下,秩保持不变
  • 将秩相同的两棵树进行合并,合并后,根结点的秩加1

在按秩合并中,我们需要维护两个数组:

  • parent数组——记录结点的双亲位置
  • rank数组——记录根结点的秩

对应的实现也很简单,如下所示:

//按秩合并
void Union_by_Rank(DSU* s, int root1, int root2) {
   
	if (root1 != root2) {
   
		if (s->rank[root1] > s->rank[root2]) {
   
			s->parent[root2] = root1;//低秩合并到高秩中
		}
		else {
   
			s->parent[root1] = root2;
			if (s->rank[root1] == s->rank[root2]) {
   
				s->rank[root2] 
http://www.dtcms.com/a/98289.html

相关文章:

  • Windows catime 番茄时钟-v1.0.5-开源简洁的 Windows 倒计时工具,支持番茄时钟功能
  • Enhanced PEC-YOLO:电力施工场景安全装备检测的轻量化算法解析
  • 树莓派超全系列文档--(12)如何使用raspi-config工具其一
  • 处理 Linux 信号:进程控制与异常管理的核心
  • JSP(实验):带验证码的用户登录
  • JavaScript基础知识初步掌握
  • 【免费】2007-2019年各省地方财政文化体育与传媒支出数据
  • 19839 Dijkstra求最短路1
  • kettle从入门到精通 第九十三课 ETL之kettle kettle 调用web service接口5种方法,一文彻底搞懂
  • c++学习系列----005.c++模板(类模板)
  • 人工智能在自然语言处理中的应用:从理论到实践的探索
  • 在一个scss文件中定义变量,在另一个scss文件中使用
  • 【Linux】——文件(上)
  • 缓存使用纪要
  • mcp 接freecad画齿轮
  • 《Python Web网站部署应知应会》No4:基于Flask的调用AI大模型的高性能博客网站的设计思路和实战(上)
  • 阅读分析Linux0.11 /boot/bootsect.s
  • 显示文献是几区的免费科研插件easyScholar
  • 基于盛科CTC7132交换机核心模块
  • SpringBoot (一) 自动配置原理
  • 字典翻转教学
  • 买卖股票的最佳时机(121)
  • Kubernetes对象基础操作
  • 现代几何风海报标签徽标logo设计psai衬线英文字体安装包 Myfonts – Nexa Serif Font Family
  • 精通React JS中的API调用:示例指南
  • RAG基建之PDF解析的“无OCR”魔法之旅
  • ESP-01模块连接手机热点问题及解决方法
  • nacos 外置mysql数据库操作(docker 环境)
  • 如何迁移AxureCloud到新服务器?
  • Jenkins插件安装失败如何解决