【高阶数据结构(一)】并查集详解

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:高阶数据结构专栏⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多Go语言知识
  🔝🔝


在这里插入图片描述

高阶数据结构

  • 1. 前言
  • 2. 并查集的原理
  • 3. 并查集的实现
  • 4. 并查集的应用
  • 5. 总结以及拓展

1. 前言

本系列会带大家走进高阶数据结构的学习, 其中包括并查集,图论, LRU cache, B树, B+树, B*树, 跳表. 其中, 图论中讲解的时间最长, 包括邻接表, 邻接矩阵, 广度优先遍历, 深度优先遍历, 最小生成树, 以及prim算法, dijkstra算法, bellman-Ford算法, Floyd-wars hall算法. 高阶数据结构属于拓展内容, 建议把基础掌握好后再学

本章重点:

本篇文章着重讲解并查集的原理, 并查集的实现(CPP),以及并查集的应用


2. 并查集的原理

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-find set)。

比如, 公司招的10个人当中有4人是北京的,三人是上海的,3人是深圳的. 那么他们就可以被分为三个不同的集合. 现在将他们进行编号(0~9),然后来看看如何将他们进行分组(为什么初始值为-1,后面再解释)

在这里插入图片描述

北京学生: 0,6,7,8.上海学生: 1,4,9.深圳学生: 2,3,5
假如选出0,1,2号学生作为小组的组长

在这里插入图片描述

现在需要在数组中,表示三个分组, 不卖关子,直接讲解并查集的原理. 当组长的人的位置的值是负数,-n代表这个组有n个人. 而非组长的成员的位置的值存储的是组长的下标,这样说可能有点抽象,下面来画个图看看

在这里插入图片描述

北京小组的组长是0,它的值是-4代表此小组有四个人.6,7,8是0的组员,所以它们存储的值是0,也就是组长的下标. 所以刚开始初始值为-1,代表每一个数都自成一个集合

现在出现一个情况, 由于北京的同学和上海的同学经常在一起玩耍, 所以久而久之他们就很熟了,就想着将这两个分组合并.于是出现了以下的情况:

在这里插入图片描述

此时,下标为1的位置应该存储它的父亲,也就是0,下标为4.9的位置不能直接存储0,而是应该存储1,因为1才是他们的直系父亲. 可以用下图来表示:

在这里插入图片描述

你可以窥探到,下标为0的值从-4变为-7,而下标为1的值从-3变为0,实际上就为我们后面的手撕并查集提供了思路


3. 并查集的实现

在进行并查集实现时,应该要拥有这几个基础功能函数: 找到一个下标的根, 合并两个集合, 判断两个树是否在同一个集合. 计算此并查集一共有几个集合.

并查集的本质是数组,所以可以这样定义结构:

class UnionFindSet
{
public:
	UnionFindSet(size_t n):_ufs(n,-1)//初始化数组,初始值设为-1
private:
	vector<int> _ufs;	
};

首先可以先实现,找到一个下标的根,后续的函数可以复用它:

int FindRoot(int x)//找到一个下标的根
{
	int parent = x;
	while (_ufs[parent] >= 0)
		parent = _ufs[parent];
	//路径压缩.下次查找时效率就高了(压缩当前节点以及它的父亲节点)
	while (_ufs[x] >= 0)
	{
		int tmp = _ufs[x];
		_ufs[x] = parent;
		x = tmp;
	}
	return parent;
}

这份代码可以分为两步,第一步就是在找它的根,就是一直向前找直到遇见负数.第二部分的代码在进行路径压缩工作,若是有多个集合进行合并,那么我们的树可能就会很高,查找最下面的树的根时,就会出现效率低下的问题,所以进行路径压缩很有必要. 关于路径压缩的原理如下:

在这里插入图片描述
下次再查找4的时候,就优化了时间

接下来的代码就简单了:

#pragma once
#include<vector>
#include<iostream>
using namespace std;
class UnionFindSet
{
public:
	UnionFindSet(size_t n):_ufs(n,-1)
	{}
	void Union(int x1, int x2) //合并两个集合
	{
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);
		if (root1 == root2) return;
		if (_ufs[root1] < _ufs[root2])
		{
			_ufs[root1] += _ufs[root2];
			_ufs[root2] = root1;
		}
		else
		{
			_ufs[root2] += _ufs[root1];
			_ufs[root1] = root2;
		}
	}
	int FindRoot(int x)//找到一个下标的根
	{
		int parent = x;
		while (_ufs[parent] >= 0)
			parent = _ufs[parent];
		//路径压缩.下次查找时效率就高了(压缩当前节点以及它的父亲节点
		while (_ufs[x] >= 0)
		{
			int tmp = _ufs[x];
			_ufs[x] = parent;
			x = tmp;
		}
		return parent;
	}
	bool SameSet(int x1, int x2)//判断这两个数是否在同一个集合
	{
		return FindRoot(x1) == FindRoot(x2);
	}
	size_t SetSize()//这个并查集一共有几个集合
	{
		size_t size = 0;
		for (auto x : _ufs)
			if (x < 0)
				size++;
		return size;
	}
private:
	vector<int> _ufs;	
};

判断两个数是否在同一集合,以及一共有几个集合,这两个函数比较简单,不做讲解. 合并两个集合先要找到这两个数的根,如果这两个数有相同的根就直接返回,否则就开始合并.合并的逻辑也非常简单,其中的if,else语句不是必须的


4. 并查集的应用

由于我是学生,所以我先给大家看看并查集在校招中考察的多不多,这道题: 省份数量是19年美团笔试的原题,并且今年24年的笔试疑似也出现过并查集解题. 除此之外, 华为考察算法和数据结构也比较厉害.其中的考点之一就有并查集:

在这里插入图片描述

并查集往往用于解决图上的问题,并查集只有两个操作,“并” 和 “查”,但是通过这两个操作可以派生出一些其他的应用:

  • 图的连通性问题
  • 集合的个数
  • 集合中元素的个数

并且在后面学习图论的过程中,也会涉及到并查集的知识,会复用并查集的代码. 这也是我优先讲并查集的原因之一, 如果你没有学过并查集直接去搞图论,可能会十分吃力


5. 总结以及拓展

并查集只是高阶数据结构中的开胃菜,后面的数据结构会越来越难,请大家耐心学习


🔎 下期预告:图论 🔍

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上传文件到 linux

一、mac 法一&#xff1a;scp 先进入mac的 Node_exporter文件&#xff08;要上传的文件&#xff09;目录下 输入scp -P 端口号 文件名 rootIP:/存放路径 scp -P 22 node_exporter-1.8.0.linux-amd64.tar.gz root192.***.2:/root 法二、 rz mac 安装 lrzsz&#xff0c;然后…

社交媒体数据恢复:batchat

蝙蝠聊天数据恢复方法 1. 数据恢复的基本原理 蝙蝠聊天的聊天记录一旦删除是不能够恢复的。这是因为蝙蝠聊天的聊天记录是保存于本地的&#xff0c;一旦删除&#xff0c;就如同在电脑或手机上删除文件一样&#xff0c;数据不会存储在服务器端。这意味着&#xff0c;如果你删除…

如何远程连接办公室电脑?

远程办公成为了现代工作生活的一部分&#xff0c;特别是在面对突如其来的疫情时&#xff0c;远程连接办公室电脑成为了一种常见的解决方案。通过远程连接&#xff0c;员工可以在不在办公室的情况下&#xff0c;直接访问办公室电脑上的文件和应用程序&#xff0c;实现远程协作和…

UE5(射线检测)学习笔记

这一篇会讲解射线检测点击事件、离开悬停、进入悬停事件的检测&#xff0c;以及关闭射线检测的事件&#xff0c;和射线检测蓝图的基础讲解。 创建一个简单的第三人称模板 创建一个射线检测的文件夹RadiationInspection&#xff0c;并且右键蓝图-场景组件-命名为BPC_Radiation…

阅读欣赏推荐之(六)——纪录片《阿基米德的秘密》

阿基米德是古希腊物理学家、数学家&#xff0c;静力学和流体静力学的奠基人。有人评价说除了伟大的牛顿和伟大的爱因斯坦&#xff0c;再没有一个人像阿基米德那样为人类的进步做出过这样大的贡献。即使是牛顿和爱因斯坦&#xff0c;也都曾从他身上汲取过智慧和灵感。他是“理论…

[暂未实现]APP签名不同保留数据覆盖安装记录

APP签名不同无法直接覆盖安装 使用adb可以卸载应用同时保留数据&#xff0c;但签名不同也无法覆盖安装&#xff08;安装原来签名的应用打开和卸载前一样&#xff09; 使用adb导出应用数据&#xff08;QQ&#xff09;db文件只有1kb&#xff0c;显然此方法也行不通

FreeBSD下安装Linux兼容系统Ubuntu

FreeBSD有个很神奇的功能&#xff0c;就是跟Linux二进制兼容&#xff0c;也就是可以直接运行linux的bin文件。还有个更神奇的功能&#xff0c;就是能运行出一套Linux系统&#xff0c;完全是linux的用户&#xff0c;linux的目录系统&#xff0c;而且还可以选是Centos系统还是Ubu…

在离线环境中将运行 Oracle DB 12c 的 CentOS 7.5 原地升级并迁移至 RHEL 7.9

《OpenShift / RHEL / DevSecOps 汇总目录》 说明 本文只是说明如何在 CentOS 7.5 上准备 Oracle DB 12c 验证环境&#xff0c;而将该环境升级并迁移至 RHEL 7.9 的操作过程请参见&#xff1a;《在离线环境中将 CentOS 7.5 原地升级并迁移至 RHEL 7.9》一文。 另外&#xff…

DEM(高程)数据下载及计算可见性

数据下载 下载链接: 地理空间数据云 (gscloud.cn) 数据部分介绍 ASTER是美国宇航局Terra航天器(1999年发射)上的五台仪器之一,在日本为经济产业省(METI)建造。美国/日本联合科学团队负责仪器设计、校准和数据验证。 高级星载热发射和反射辐射计(ASTER)全球数字高程…

Android BINDER是干嘛的?

1.系统架构 2.binder 源码位置&#xff1a; 与LINUX传统IPC对比

【c++设计模式15】结构型7:代理模式(Proxy Pattern)

【c设计模式15】结构型7&#xff1a;代理模式&#xff08;Proxy Pattern&#xff09; 一、定义二、适用场景三、过程四、代理模式类图五、C示例代码六、使用注意事项七、结论 类型序号设计模式描述结构型1适配器模式&#xff08;Adapter Pattern&#xff09;它用于在不修改已有…

一次完整的 http 请求是怎样的?

一次完整的 http 请求是怎样的&#xff1f; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 域名解析 --> 发起 TCP 的 3 次握手 --> 建立 TCP 连接后发起 http 请求 --> 服务器响应 http 请求&#xff0c;浏览器得到 html 代码 --…

Activating More Pixels in Image Super-Resolution Transformer

cvpr2023https://github.com/XPixelGroup/HAT?tabreadme-ov-file问题引入&#xff1a; – 现在的transformer based的SR模型“感受野”不够&#xff1b; – 分析&#xff1a;原本认为transformer-based的方法优于CNN-based的方法是因为可以利用更加long-range的信息&#xff0…

MySql数据库(概念篇)

数据库概念 什么是数据库 数据库见名之意&#xff0c;就是用来存储数据的仓库&#xff0c;是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。 没接触数据库之前&#xff0c;一般都是将数据存储在文件中。比如execl文件&#xff0c;word文件中。但是…

基于 Dockerfile 部署 LNMP 架构

目录 前言 1、任务要求 2、Nginx 镜像创建 2.1 建立工作目录并上传相关安装包 2.2 编写 Nginx Dockerfile 脚本 2.3 准备 nginx.conf 配置文件 2.4 生成镜像 2.5 创建 Nginx 镜像的容器 2.6 验证nginx 3、Mysql 镜像创建 3.1 建立工作目录并上传相关安装包 3.2 编写…

flink sql 优化

文章目录 一、参数方面二、资源方面三、总结 提示&#xff1a;实时flink sql 参考很多网上方法与自己实践方法汇总(版本:flink1.13) 一、参数方面 flink sql参数配置 //关闭详细算子链(默认为true),true后job性能会略微有提升。false则可以展示更详细的DAG图方便地位性能结点…

4. HBuilderX中的插件商城

前言 在HBuilderX中有一个插件市场&#xff0c;这个和VSCode的插件库不太像&#xff0c;硬要做个简单类比的话&#xff0c;个人认为HBuilderX中的插件市场更像是npm库&#xff0c;它里面有许多其他开发者开发的插件&#xff0c;这些插件更多的是为uniapp服务的&#xff0c;比如…

第23章 微内核架构软件测试(下午题)

一、微内核架构概述 &#xff08;一&#xff09;概念 1、微内核架构 微内核&#xff1a;精简的内核 宏内核&#xff1a;中央集权控制中心 核心系统 能运行的最小模块插件模块 专业处理&#xff0c;额外特性的独立组件增加/扩展核心系统的业务逻辑能力连接方式 OSGI、消息机…

springAI框架学习总结

springAI 1.springAI基本介绍 springAI是一个AI工程应用框架&#xff0c;其目标是将 Spring 生态系统设计原则&#xff08;例如可移植性和模块化设计&#xff09;应用于 AI 领域&#xff0c;并推广使用 POJO 作为 AI 领域应用程序的构建块。 2.特性 灵活的AIP支持chat,text…

WPF之绑定属性值转换

1&#xff0c;使用Binding.Format属性简易设置绑定的属性数据显示格式。 <TextBox Grid.Row"2" Grid.Column"1"><TextBox.Text><Binding Path"UnitCost" StringFormat"{}{0:C3}" > …