【数据结构】并查集

2023-11-20

1.并查集原理

并查集是一种树型的数据结构,用于处理一些不相集合的合并及查询问题。常常在使用中以森林来表示。

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

比如现在有这样的情况:

目前饭局有10个人,没两个人之间都可能存在远方亲戚关系,如何将个人分成不同的家庭?现在将个人编号为{0,1,2,3,4,5,6,7,8,9}

在这里插入图片描述

-1表示假设每个人之间都不存在亲戚关系

接下来,饭局中的人互相交谈,了解到自己的亲戚关系,因此可以形成不同的家庭。比如:当前是s1:{0,6,7,8},s2:{1,4,9},s3:{2,3,5}形成了不同的家庭。

在这里插入图片描述

用树模型表示

在这里插入图片描述

因此规定并查集数组有下面的规定:

  1. 数组的下标对应集合中元素的编号
  2. 数组中如果为负数,负号代表根,数字代表该集合中元素个数
  3. 数组中如果为非负数,代表该元素双亲在数组中的下标

如果此时0和1发现也有亲戚关系,那么s1和s2可以合并为一个新的家庭

在这里插入图片描述

并查集需要有下面的接口

  • 查找元素属于哪个集合
  • 查看两个元素是否属于一个集合
  • 合并两个集合
  • 集合的个数

2.并查集的实现

2.1并查集框架
template<class T>
class UnionFindSet
{
public:
    //构造函数
    UnionFindSet(){}
    //插入元素接口
    bool insert(T t);
    //查找所属集合
    int Findroot(T t);
    //合并两个集合
    void Union(T t1,T t2);
    //统计并查集中一个有多少个集合
    size_t count();
private:
    unordered_map<T, int> mp;	//存放内容和下标的对应关系
	unordered_map<int, T>mpt;	//存放下标和存放内容的对应关系
	vector<int>_fa;				//存放父亲下标的数组
}
2.2insert()插入元素接口

在vector容器中插入新的元素,并作为一个单独的集合

bool insert(T t)
{
	auto it = mp.find(t);
	if (it != mp.end())
	{
		return false;
	}
	int size = _fa.size();
	mp[t] = size;
	mpt[size] = t;
	_fa.push_back(-1);
}
2.3Findroot查找所属集合
int Findroot(T t)
{
	auto it = mp.find(t);
    if (it==mp.end()){
			return -1;
		}
	int x = mp[t];
	int father = _fa[x];
	if (father < 0){
		return x;
	}
	string fs = mpt[father];
	return _fa[x] = Findroot(fs);	//路径压缩
}
2.4合并两个集合
void Union(T t1,T t2)
{
	if (mp.find(t1) == mp.end() || mp.find(t2)==mp.end())
	{
		return;
	}
	int fa1 = Findroot(t1);
	int fa2 = Findroot(t2);
	if (fa1 != fa2)
	{
		_fa[fa1] += _fa[fa2];
		_fa[fa2] = fa1;
	}
}
2.5统计集合个数

如果_fa[ x ]的值为负数,那么就属于是一个单独的集合

size_t count(){
	int cnt = 0;
	for (auto i : _fa){
		if (i < 0) {
			cnt++;
		}
	}
	return cnt;
}

3.测试

用饭局找亲戚例子检测并查集。

void test(UnionFindSet<string>&u)
{
	u.insert("人0");u.insert("人1");u.insert("人2");u.insert("人3");
	u.insert("人4");u.insert("人5");u.insert("人6");u.insert("人7");
	u.insert("人8");u.insert("人9");
	u.Union("人0", "人6");u.Union("人0", "人7");u.Union("人0", "人8");
	u.Union("人1", "人4");u.Union("人1","人9");u.Union("人2", "人3");
	u.Union("人2", "人5");
}
int main()
{
	UnionFindSet<string> u;
	test(u);
	size_t x1 = u.Findroot("人7");
	size_t x2 = u.Findroot("人3");
	cout << x1 << endl;
	cout << x2 << endl;
	u.Union("人0", "人2");
	size_t x3 = u.Findroot("人5");
	cout << x3 << endl;
	return 0;
}

在这里插入图片描述

最后得到目标输出

在这里插入图片描述

4.并查集OJ

4.1省份的数量

剑指 Offer II 116. 省份数量 - 力扣(LeetCode)

在这里插入图片描述

class Solution {
public:
    //查找所属集合
    int find(vector<int>&fa,int x){
        return fa[x]==x?x:fa[x]=find(fa,fa[x]);
    }
    int findCircleNum(vector<vector<int>>& isConnected) {
        int n=isConnected.size();
        vector<int>fa(n,0);
        //初始化
        for(int i=0;i<n;i++){
            fa[i]=i;
        }
        //union
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(isConnected[i][j]==1){
                    int fi=find(fa,i),fj=find(fa,j);
                    if(fi!=fj){
                        fa[fj]=fi;
                    }
                }
            }
        }
        int cnt=0;
        for(int i=0;i<n;i++){
            if(i==fa[i]){
                cnt++;
            }
        }
        return cnt;
    }
};
4.2等式方程的可满足性

990. 等式方程的可满足性 - 力扣(LeetCode)

在这里插入图片描述

class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        vector<int>fa(26,-1);
        auto findroot=[&fa](int x)->int{
            while(fa[x]>=0){
                x=fa[x];
            }
            return x;
        };
        //第一次遍历,将相等的字母合并到同一个集合中
        for(auto str:equations){
            if(str[1]=='='){
                int root1=findroot(str[0]-'a');
                int root2=findroot(str[3]-'a');
                if(root1!=root2){
                    fa[root2]=root1;
                }
            }
        }
        //第二次遍历,如果题目要求俩个字母属于不同的集合,但是在第一次遍历的过程中合并到一个集合中,说明等式方程不满足
        for(auto str:equations){
            if(str[1]=='!'){
                int root1=findroot(str[0]-'a');
                int root2=findroot(str[3]-'a');
                if(root1==root2){
                    return false;
                }
            }
        }
        return true;
    }
};
4.3图是否是树

178 · 图是否是树 - LintCode

在这里插入图片描述

class Solution {
public:
    int find(vector<int>f,int x){
        return f[x]==x?x:find(f,f[x]);
    }
    bool validTree(int n, vector<vector<int>> &edges) {
        vector<int>f(n);
        //初始化并查集,将每一个元素作为一个单独的集合
        for(int i=0;i<n;i++){
            f[i]=i;
        }
        for(int i=0;i<edges.size();i++){
            int u=edges[i][0],v=edges[i][1];
            //寻找两个点的父亲节点
            int fu=find(f,u),fv=find(f,v);
            //如果此时,父亲节点相同,这成环
            if(fu==fv){
                return false;
            }
            else{
                f[fv]=fu;
            }
        }
        int cnt=0;
        for(int i=0;i<n;i++){
            if(f[i]==i){
                cnt++;
            }
        }
        return cnt==1;
    }
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数据结构】并查集 的相关文章

  • eclipse juno 打开时出错

    在安装 Eclipse 并正常工作一年多后 我今天打开 Eclipse Juno 并在打开工作区时收到一条错误消息 我使用的是 Windows 8 64 位 Java 64 位和 Eclipse 64 位 此后我尝试重新安装 Java 和
  • 如何在流中收集到TreeMap中?

    我有两个Collectors groupingBy在流中 我需要收集所有信息TreeMap 我的代码 Map
  • 无法从 TemporalAccessor 获取 OffsetDateTime

    当我这样做时 String datum 20130419233512 DateTimeFormatter formatter DateTimeFormatter ofPattern yyyyMMddHHmmss withZone ZoneI
  • Selenium - 保存网站,包括所有图像、css、dom

    我想使用 firefox 或 chrome 访问带有 selenium 的页面 当页面加载时 我想从页面下载所有图像 css dom 我想存储每张图像 就像我在其中找到它们一样 chrome gt Tools gt Development
  • 可以向 @ManyToMany Hibernate 额外表添加额外字段吗?

    我有这两类 表 Entity Table name course public class Course Id Column name courseid private String courseId Column name coursen
  • PrintStream是有缓冲的,但是flush不会降低性能,而BufferedOutputStream会加速性能

    我预计由于 PrintStream 是缓冲的 通过在每次 print 之后添加刷新操作 速度性能应该会显着降低 但事实并非如此 如下面的代码片段所示 此外 将 PrintStream 包裹在 BufferedOutputStream 周围可
  • 将 emoji 替换为适当的 java 代码

    我正在开发一个简单的java程序 它可以接受这样的字符串 停止 你违反了 法律 但是现在 你 并将每个表情符号替换为适当的 java 字符 我不知道该怎么称呼他们 这是一个例子 汽车表情符号 将替换为 uD83D uDE97 这允许我有一个
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • 从 org.w3c.dom.Node 获取 Xpath

    我可以从 org w3c dom Node 获取完整的 xpath 吗 假设当前节点指向 xml 文档中间的某个位置 我想提取该元素的 xpath 我正在寻找的输出 xpath 是 parent child1 chiild2 child3
  • 在 Java 5 及更高版本中迭代 java.util.Map 的所有键/值对的最简单方法是什么?

    在 Java 5 及更高版本中迭代 java util Map 的所有键 值对的最简单方法是什么 假设K是您的密钥类型 并且V是你的值类型 for Map Entry
  • 如何连接hibernate和DB2

    我正在运行一个使用 struts 和 hibernate 的应用程序 我目前正在使用 Derby 数据库 现在我必须转向 DB2 数据库 请告诉我 我必须做什么配置 休眠配置文件 我必须设置任何类路径吗 多变的 我知道 DB2 有两个 ja
  • 在 javafx 中注册鼠标处理程序,但处理程序不是内联的

    我有一个 JavaFX 应用程序变得有点大 我想保持代码的可读性 我有一个折线图 我希望内置缩放功能 该功能在单击鼠标时发生 我知道我需要向图表注册鼠标侦听器 我无法从 Oracle 示例中弄清楚什么 即如下所示 http docs ora
  • 为什么 Java 中的 hashCode() 可以对不同对象返回相同的值?

    引用我正在读的书中的一段话首先Java http www amazon co uk Head First Java Kathy Sierra dp 0596009208 关键是 哈希码可以相同 但不一定保证对象相等 因为使用的 哈希算法 h
  • Spring @Value 添加验证小于

    我使用以下属性值注入 我如何向此操作添加小于验证 我的意思是我想设置一个验证user maxpassiveday可以说 财产价值不得低于 100 Value user maxpassiveday int maxpassiveday 使用Sp
  • JSP 作为电子邮件模板

    有没有办法发送 MIME 电子邮件 其中电子邮件正文源自 JSP 我需要使用 Javamail 发送一封电子邮件 其中包含一个表格 我认为如果我可以使用 JSP 来完成所有格式设置和布局 将会很方便 在这个线程中 Java 电子邮件模板的建
  • Android - 保持用户登录状态

    我正在尝试使用 PHP 和 MySQLi for Android 进行登录 我不明白的是如何保持用户登录状态 我看到一个简单的教程 其中有人使用 SQLite 来保护信息 但我不知道这是否真的安全 如何保存用户信息以保持用户登录状态 谢谢
  • WebSocketStompClient 将无法连接到 SockJS 端点

    我正在尝试新的 从版本 4 2 开始 java STOMP 客户端支持 我的出发点是入门指南 使用 WebSocket 构建交互式 Web 应用程序 http spring io guides gs messaging stomp webs
  • Android应用程序中的模式输入

    我想知道是否有其他替代方案可以替代 Android 上平庸的 EditText 密码输入 是否有 API 或开源代码可以集成到我的应用程序中 类似于锁屏图案解锁 Intent 可能会返回哈希值 数字 字符串或代表用户输入的模式的任何内容 我
  • RecyclerView 适配器的 Kotlin 泛型

    我正在尝试编写一个通用的 recyclerview 适配器 我找到了几个例子 然而 仍然无法弄清楚如何实现通用适配器 我写的代码是 open abstract class BaseAdapter
  • 对 Java 协议缓冲区对象进行一些小更改

    我想在 Java 协议缓冲区对象树的深处进行一个小更改 我可以使用 getBuilder 方法来创建一个新对象 该新对象是旧对象的克隆并进行一些更改 当深入完成此操作时 代码会变得丑陋 Quux Builder quuxBuilder fo

随机推荐

  • 计算机网络重点知识(期末考研复习)

    点个关注 更多精彩持续更新为考研和期末助力 一起加油 计算机网络 第一章 思维导图 概述 计算机网络的主要性能指标 计算机网络的体系结构 OSI RM模型 TCP IP 两种模型对比 第二章 思维导图 数据通信主要指标与信道极限容量 多路通
  • java8新特性学习笔记

    使用lambda表达式排序 Collections sort temp String a String b gt return b compareTo a Collections sort temp String a String b gt
  • Camera2拍照时部分机型非常暗

    一 问题描述 1 部分手机在弱光环境下不管什么分辨率 预览和拍出来的照片都非常的暗 2 部分手机在弱光环境下 预览分辨率1920x1080 输出图片分辨率1920x1080时 预览和拍出来的照片亮度比较亮 但是在预览分辨率1920x1080
  • 重现U盘文件

    U盘中毒了 查毒后发现U盘空间还在 但是就是无法查看里面的文件 在 工具 gt 文件夹选项 中设置成 显示系统文件夹中的内容 去掉 隐藏受保护的操作系统文件 推荐 以及设置成 显示所有文件和文件夹 也不能正常显示 最近遇到很多优盘中的文件夹
  • 图像特征提取技术

    目 录 前 言 基于颜色的特征提取 1 颜色空间 2 直方图以及特征提取 基于纹理的特征提取 1 灰度共生矩阵 2 tamura纹理 基于深度神经网络的图像处理 前 言 图像特征提取属于图像分析的范畴 是数字图像处理的高级阶段 本文将从理论
  • SeleniumLibrary4.5.0 关键字详解(三)

    SeleniumLibrary4 5 0 关键字详解 三 库版本 4 5 0 库范围 全局 命名参数 受支持 简介 SeleniumLibrary是Robot Framework的Web测试库 本文档说明了如何使用SeleniumLibra
  • 获取对象Object的长度

    获取对象的长度 obj id 1 id2 1 id3 1 id4 1 id5 1 id6 1 id7 1 id8 1 id9 1 id10 1 let i Object keys this obj length console log i
  • 嵌入式linux 搭建L2TP+IPSEC客户端

    搭建L2TP IPSEC客户端需要对应的源码 xl2tpd 1 3 10和openswan 还需要一些依赖的库 gmp libpcap 一 安装openswan 安装依赖库gmp 6 1 2 1 下载 https gmplib org DO
  • C#操作SqlServer数据库,以及其常用的对象

    C 操作SQL Server数据库 1 概述 ado net提供了丰富的数据库操作 这些操作可以分为三个步骤 第一 使用SqlConnection对象连接数据库 第二 建立SqlCommand对象 负责SQL语句的执行和存储过程的调用 第三
  • 服务器备案问题解决思考?

    大家和我一样有没有在项目上线之后遇到服务器需要备案的问题呢 遇到这个问题的原因 域名没有备案 可是我发现我域名本案后还是无法通过域名直接解析到服务器80端口 所以我百度后发现 服务器竟然也要备案 而且备案步骤 手续与域名备案相比是真的麻烦
  • Docker搭建mysql主从

    目录 1 安装配置master 1 1 运行mysql容器 1 2 更新基础软件和安装vim 1 3 编辑配置文件 1 4 创建用户并授权 用于再主从库之间同步数据 2 slave数据库安装配置 2 1 运行容器 2 2 进入容器内部 2
  • JavaWeb的高级、Listener监听器--Servlet事件

    一 学习目标 1 Listener监听器 2 Listener监听器作用 3 Listener监听器的创建与销毁 二 重点知识 1 Listener监听器 Filter和Listener是Servlet规范中的两个高级特性 不同于Servl
  • vue项目打包后如何本都部署访问

    npm run build生成dist项目后 在windows部署访问 方式一 1 新建一个文件夹 进入目录后打开cmd 输入npm init y 2 输入 npm i express s 是用于在 Node js 项目中安装 Expres
  • 小程序实现微信登录Java后端(一)--前端实现

    目录 一 概述 二 登录流程 三 前端代码 四 解读前端代码 1 登录部分 2 检查当前用户是否已登录 3 小程序启动时校验登录 五 阶段性小结 一 概述 最近终于有时间去搞一下准备参加比赛的小程序 小程序一开始设计的是使用邮箱登录 老师建
  • 剑指offer——输出数组中k个最小值(快速,冒泡,选择,插入)

    找k个最小值 基本思路是对数组排序 输出前k个或者后k个 我们回顾一下之前的学习过的集中排序方法 快速排序 class Solution def GetLeastNumbers Solution self tinput k def quic
  • rust房屋建造蓝图_妄想山海房子建造攻略

    妄想山海这个游戏的一大特色就是玩家可以在游戏里建造属于自己的房屋 而且这个房屋可不是几个图或是简单的3d模型 而是一个完整的房屋呦 玩家可以创作或是收集来的房屋设计图 真实打造 所以在妄想山海里房子的建造还是要花点功夫的 下面讯喵喵就为大家
  • Redis 分布式缓存

    分布式缓存 单点 Redis 的问题及解决 数据丢失 实现Redis数据持久化 并发能力 搭建主从集群 实现读写分离 存储能力 搭建分片集群 利用插槽机制实现动态扩容 故障恢复能力 利用哨兵机制 实现健康检测和自动恢复 RDB RDB全称R
  • 利用接口请求获取文件

    1 背景 测试阶段文件上传服务器为测试文件服务器 预览时根据id获取的测试服务器文件 但发到线上后发现文件上传到了测试服务器 读取文件时又是从线上的文件服务器读取的 因此导致了文件显示异常 2 数据恢复分析 先从测试环境获取到文件 这些文件
  • 微信小程序图片使用filter将彩色图片变成黑白以后,border-radius失效的解决办法

    使用css的filter将彩色图片亮度降低之后 设置的border radius会出现失效不起作用的情况 需求 用户在线头像为原始的彩色图片 离线将用户头像改为黑白色 原来的写法
  • 【数据结构】并查集

    文章目录 1 并查集原理 2 并查集的实现 2 1并查集框架 2 2insert 插入元素接口 2 3Findroot查找所属集合 2 4合并两个集合 2 5统计集合个数 3 测试 4 并查集OJ 4 1省份的数量 4 2等式方程的可满足性