news 2026/3/22 20:06:46

数据结构之并查集

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据结构之并查集

一、并查集的原理

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

比如作者有大学同学,高中同学,初中同学,他们彼此不认识。就会分为三个集合。

按10人来算,将其按编号分为0-9,

分为不同的团体

用数组来表示该树形关系,数组中的非负数代表其父节点,负数表示该结点为根结点,且该树形有abs(负数)个结点。

之后,机缘巧合下,大学同学和初中同学在一场聚会中认识了,就将其合并为一个集合。

通过以上例子可知并查集一般可解决以下问题:

1.查找元素属于哪一个集合
2.查看两个元素是否属于同一个集合
3.将两个集合归并为一个集合
4.得到集合的个数

二、并查集的实现

1.这里我使用map存储名字和其对应vector的下标,vector来存储其关系。
class UnionFindSet{ public: UnionFindSet(int n) { v.reserve(n); } private: vector<int> v; map<T,int> m; };
2.push实现去添加新元素
void push(T&& name) { v.push_back(-1); m[name] = v.size() - 1; } void push(const T& name) { v.push_back(-1); m[name] = v.size()-1; }

这里实现右值引用和const左值引用两个版本

3.给一个元素,找见其元素所在集合的位置
//给一个元素,找见其元素所在集合的位置 int UnionFind(const T& name) { if (m.count(name) == 0) { return -1; } else { //通过循环遍历,找见v[index]为负数的位置 //该index就为根节点的位置 int index= m.find(name)->second; while (v[index] >= 0) { index = v[index]; } return index; } }
4.查找集合的个数
//集合的个数 size_t Count()const { size_t count = 0; for (int i = 0; i < v.size(); i++) { if (v[i] < 0) { count++; } } return count; }
5.查找两个元素是否为同一个集合,并合并
//合并两个元素为同一个集合 bool merge(const T& name1, const T& name2) { //查找两个元素是不是同一个集合 int x1 = UnionFind(name1); int x2 = UnionFind(name2); if (x1 == x2) {//因为有相同的根节点,所以为同一个集合 return false; } else { v[x1] += v[x2];//将v[x2]存储的内容加在v[v1]上更新新集合的结点数量 v[x2] = x1;//将v[x2]指向父节点 return true; } } //也可合并多个元素,利用可变参数包 template<class...Args> void merge(const T& name1, const T& name2, Args&&... args) { merge(name1, name2); if constexpr (sizeof...(args) > 0) {//constexpr可以在编译时检查,防止传参出现问题 merge(name2, forward<Args>(args)...);//这里用完美转发去保持其右值属性不变。 } }

三、并差集的应用

1.省份数量https://leetcode.cn/problems/number-of-provinces/description/
class Solution { public: int findCircleNum(vector<vector<int>>& isConnected) { vector<int> v; v.resize(isConnected.size(),-1); auto find=[&v](int index){//寻找根节点的数组下标 while(v[index]>=0){ index=v[index]; } return index; }; auto merge=[&v,&find](int a,int b){//合并两个集合 int a1=find(a); int b1=find(b); if(a1!=b1){ v[a1]+=v[b1]; v[b1]=a1; } }; for(int i=0;i<isConnected.size();i++){ for(int j=0;j<isConnected.size();j++){ if(isConnected[i][j]==1){//建立集合的关系 merge(i,j); } } } int count=0; for(int i=0;i<v.size();i++){ if(v[i]<0){//判断“省份”的数量 count++; } } return count; } };
2.等式方程的可满足性https://leetcode.cn/problems/satisfiability-of-equality-equations/description/
class Solution { public: bool equationsPossible(vector<string>& equations) { vector<int> v; v.resize(26,-1); auto find=[&v](int index){ while(v[index]>=0){ index=v[index]; } return index; }; auto merge=[&v,&find](int x,int y){ int x1=find(x); int y1=find(y); if(x1!=y1){ v[x1]+=v[y1]; v[y1]=x1; } }; for(auto& e:equations){ if(e[1]=='='){//先将等于关系建立起来 merge(e[0]-'a',e[3]-'a'); } } for(auto& e:equations){ if(e[1]=='!'){//判断两个不等的元素是否有相等关系 int x=find(e[0]-'a'); int y=find(e[3]-'a'); if(x==y){//有就返回失败 return false; } } } return true;//遍历结束返回成功 } };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/22 17:18:04

Linly-Talker在公务员面试培训中的模拟考官应用

Linly-Talker在公务员面试培训中的模拟考官应用 在公务员考试竞争日益激烈的今天&#xff0c;面试环节的准备早已不再局限于“背模板”和“练套路”。越来越多考生意识到&#xff0c;真正的高分回答不仅需要内容扎实&#xff0c;更要在表达逻辑、情绪控制、临场反应等方面展现出…

作者头像 李华
网站建设 2026/3/13 19:27:08

数字人直播切片:自动生成精彩片段用于二次传播

数字人直播切片&#xff1a;自动生成精彩片段用于二次传播 在电商直播动辄持续数小时的今天&#xff0c;一场看似热闹的带货背后&#xff0c;真正能被观众记住的内容可能只有几分钟——某个爆款产品的限时优惠、一句极具感染力的情绪表达&#xff0c;或是主播脱口而出的“闭眼入…

作者头像 李华
网站建设 2026/3/13 16:53:07

AI导游多语种支持:服务国际游客的实用方案

AI导游多语种支持&#xff1a;服务国际游客的实用方案 在巴黎卢浮宫&#xff0c;一位日本游客指着《蒙娜丽莎》轻声提问&#xff1a;“这幅画为什么这么有名&#xff1f;” 几秒钟后&#xff0c;她的手机屏幕上&#xff0c;一位身着正装的虚拟讲解员微笑着开口——用流利的日语…

作者头像 李华
网站建设 2026/3/13 7:13:47

Linly-Talker与RVC结合实现更自然的歌声合成

Linly-Talker与RVC结合实现更自然的歌声合成 在虚拟主播、AI歌手和数字员工日益普及的今天&#xff0c;用户对AI表现力的期待早已超越了“能说会道”的基础阶段。人们希望看到的不再是一个机械复读的语音盒子&#xff0c;而是一个有情感、有个性、甚至能登台演唱的“活生生”的…

作者头像 李华
网站建设 2026/3/13 19:06:18

MySQL多表join的底层优化技术详解

虽然阿里内部存在上述规范&#xff0c;但在很多场景下&#xff0c;即使进行多表JOIN且数据量大&#xff0c;SQL查询效率仍然很高。其实这背后涉及多个层面的优化技术。本文我将详细解释这些看似矛盾的现象&#xff1a; 一、底层优化技术 1. 现代优化器的智能化 -- 看似复杂但能…

作者头像 李华
网站建设 2026/3/20 5:35:59

如何用Linly-Talker生成带情绪表达的数字人视频

如何用Linly-Talker生成带情绪表达的数字人视频 在短视频内容爆炸式增长的今天&#xff0c;企业培训、在线课程和品牌宣传越来越依赖高质量讲解视频。但传统制作方式成本高、周期长——请主播出镜要协调档期&#xff0c;做动画又要专业团队逐帧调整表情与口型。有没有可能“输入…

作者头像 李华