并查集及其简单应用

news2024/10/7 8:28:30

在这里插入图片描述

文章目录

  • 一.并查集
  • 二.并查集的实现
  • 三.并查集的基本应用

一.并查集

  • 并查集的逻辑结构:由多颗不相连通多叉树构成的森林(一个这样的多叉树就是森林的一个连通分量)

    • 并查集的元素(树节点)用0~9的整数表示,并查集可以表示如下: 在这里插入图片描述
  • 并查集的物理存储结构:并查集一般采用顺序结构实现,用数组下标表示并查集的元素,数组元素用于记录并查集中的元素间的关系:在这里插入图片描述

    • 并查集的元素对应的数组元素负数,则表示该并查集元素某颗多叉树的根且没有前驱结点,负数的绝对值表示该颗多叉树(并查集的连通分量)的元素个数
    • 并查集的元素对应的数组元素非负数,这个非负数则表示该并查集的元素的前驱结点
  • 并查集数据结构常用的运算就是==(连通分量)多叉树间的合并算法==:在这里插入图片描述

二.并查集的实现

  • 并查集的初始状态设置:在这里插入图片描述
  • 简单的代码实现:
#include <iostream>
#include <vector>
#include <string>

//采用适配器模式实现并查
class UnionFindSet
{
public:
	//构造函数参数为并查集中的元素个数,并查集的初始状态为size颗树构成的森林(size个连通分量)
	UnionFindSet(size_t size)
		:_SetMap(size,-1)
	{}
	//给定一个并查集元素找到其所在的(连通分量)多叉树的根结点
	size_t FindRoot(int Node) const throw(std :: string)
	{
		//越界检查
		if (Node < 0 || Node >= _SetMap.size())throw "Label out of range";	
		while (_SetMap[Node] >= 0)
		{
			Node = _SetMap[Node];
		}
		return static_cast<size_t>(Node);
	}


	//给定两个并查集元素,将它们所在的(连通分量)多叉树进行合并运算
	void Union(int Node1, int Node2)  throw(std::string)
	{
		//越界检查
		if (Node1 < 0 || Node1 > _SetMap.size()|| Node2 < 0 || Node2 > _SetMap.size())
			throw "Label out of range";

		//先找到两个元素所在的(连通分量)多叉树的根
		size_t root1 = FindRoot(Node1);
		size_t root2 = FindRoot(Node2);
		//进行多叉树合并操作
		if (root1 != root2)
		{
			_SetMap[root1] += _SetMap[root2];
			_SetMap[root2] = static_cast<int>(root1);
		}
	}

	//计算并查集中多叉树的颗数(连通分量的个数)
	size_t SetCount() const noexcept
	{
		//并查集中多叉树的颗数就是vector中负数元素的个数
		size_t count = 0;
		for (auto e : _SetMap)
		{
			if (e < 0)++count;
		}
		return count;
	}
private:
	std::vector<int> _SetMap;
};
  • 并查集是一种经常用于划分等价类的数据结构.以树形逻辑结构为基础,以一颗多叉树(一个连通分量)表示一个等价类,多个互相不连通的多叉树(连通分量)构成的森林用于表示多个等价类构成的集合,使用并查集可以很好地解决等价类的划分和计数问题(即图的连通分量的求解问题)

三.并查集的基本应用

LeetCoed : LCR 116. 省份数量

  • 这个问题就是一个等价类集合构建和计数问题,可以使用并查集解决.(题目中的相连关系就是一种相对于相同省份性质的等价关系)
  • 问题的本质可以抽象为:以城市为元素依据相连关系形成的图结构的最小生成树的个数(即连通分量的个数),可以采用dfsbfs遍历算法,此处提供使用并查集的一种写法.
  • 借助vectorlambda表达式建立简单的并查集最后返回并查集中多叉树的个数:
class Solution 
{
public:
    int findCircleNum(vector<vector<int>>& isConnected) 
    {
        //创建简易的并查集
        vector<int> UnionSet(isConnected.size(),-1);
        //定义Find函数,根据结点找到多叉树的根
        auto Find = [&UnionSet](int Node){
                        while(UnionSet[Node] >=0)
                        {
                            Node = UnionSet[Node];
                        }
                        return Node;
                    };
        for(int i = 0; i < isConnected.size(); ++i)
        {
            for(int j = i+1; j < isConnected.size(); ++j)
            {
                if(isConnected[i][j] == 1)
                {
                    //多叉树合并
                    int root1 = Find(i);
                    int root2 = Find(j);
                    if(root1 != root2)
                    {
                        UnionSet[root1] += UnionSet[root2];//这句代码用于修改结点计数,此题中可以不加
                        UnionSet[root2] = root1;
                    }
                }

            }
        }

        int count = 0;
        //统计并查集中多叉树的个数
        for(auto e : UnionSet)
        {
            if(e < 0 ) ++count;
        }
        return count;
    }
};

LeetCode:990. 等式方程的可满足性

  • 这同样是一个等价类划分的问题:将0~25的各个编号与a~z二十六个字母建立映射关系,根据字母间相等关系构建并查集:
class Solution 
{
public:
    bool equationsPossible(vector<string>& equations) 
    {
        vector<int> UionSet(26,-1);
        auto FindRoot = [&UionSet](int Node){
                            while(UionSet[Node] >= 0)
                            {
                                Node = UionSet[Node];
                            }
                            return Node;
                        };

        //先遍历等式方程中的字母,在并查集中将它们归类到各个多叉树中(构建相等关系等价类集合)
        for(auto str : equations)
        {
            //遇到等式,等式两边字母应该属于并查集中同一颗多叉树
            if(str[1] == '=')
            {
                int root1 = FindRoot(str[0]-'a');
                int root2 = FindRoot(str[3]-'a');
                if(root1 != root2)
                {
                    UionSet[root1] += UionSet[root2];
                    UionSet[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;
    }
};

在这里插入图片描述

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

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

相关文章

Springboot 项目配置Swagger2

1. 加入swagger 依赖 springboot 项目的 pom.xml 中添加下列依赖&#xff1a; <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version> </dependency> <depe…

Postgresql部署及简单操作

目录 1、介绍 2、什么是PostgreSQL 3、PostgreSQL 的特点 4、数据库定为 5、环境准备 6、编译安装 6.1 安装依赖包 6.2 下载安装包 6.3 创建用户 6.4 创建 postgresql数据目录并授权 6.5 上传压缩包并解压 6.6 编译postgresql源码 6.7 配置环境变量 6.8 初始化数…

使用 wxPython 和 pymupdf进行 PDF 加密

PDF 文件是一种常见的文档格式&#xff0c;但有时候我们希望对敏感信息进行保护&#xff0c;以防止未经授权的访问。在本文中&#xff0c;我们将使用 Python 和 wxPython 库创建一个简单的图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;用于对 PDF 文件进行加密…

2023年你会选择哪种编程语言?

2023年你会选择哪种编程语言&#xff1f; 关于编程语言的个人见解。 KOTLIN&#xff1a;由于其先进的多平台能力&#xff0c;未来5年内它很可能成为开发任何类型的客户端应用&#xff08;移动端、桌面端或Web端&#xff09;的首选编程语言。他们正在为iOS和WebAssembly开发的…

power designer 反向工程过程已中断,原因是某些字符无法通过ANSI-->UTF-16转换进行映射

起因&#xff1a;sqlserver导入sql时报错&#xff0c;一查询是power designer 反向工程过程已中断&#xff0c;原因是。某些字符无法通过ANSI-->UTF-16转换进行映射&#xff08;会导致数据丢失&#xff09; 解决办法&#xff1a; 导入成功

【Vue】全家桶之vue-Router

文章目录 概述后端路由前端路由Vue Router安装 vue-router 的常见用法路由懒加载路由重定向嵌套路由动态路由匹配 声明式导航 & 编程式导航声明式导航编程式导航 导航守卫全局前置守卫守卫方法的 3 个形参next 函数的 3 种调用方式控制后台主页的访问权限 路由的两种工作模…

骨传导耳机音质好吗?骨传导耳机音质和普通耳机对比哪个好?

相信不少朋友还是比较排斥骨传导耳机的&#xff0c;并不是说骨传导技术不成熟&#xff0c;而是骨传导对技术的要求实在太高了&#xff0c;尤其是对音质以及防漏音的考验。作为一款新兴产品&#xff0c;骨传导耳机打破了传统的传音模式&#xff0c;由空气传导&#xff0c;转变为…

element上传图片,调取接口传值,参数FormData为空

需求 输入完reason&#xff0c;选完文件后&#xff0c;点击提交按钮后 调取接口。 遇到的问题 上传文件orderFile 字段一直为空 打印了发现&#xff0c;上传文件也是有值得。但是传到接口中就为空 原因 json里边不能放file&#xff0c;但是formData里可以放 file 也可以放…

每个世界500强公司,都遇到过增长瓶颈

在《财富》100强公司的增长历程分析中&#xff0c;最容易得出的结论是大部分大型企业都曾经历过一段停滞期。这些公司的规模大小各不相同&#xff0c;尽管绝大部分停滞都发生在收入10亿—100亿美元之间的公司内&#xff0c;但任何规模的企业都有可能出现增长停滞。这是因为&…

C++学习第十五天----循环和文本输入

昨天说到使用cin进行键盘输入的一些弊端&#xff0c;那么怎么解决呢&#xff1f; 1.使用cin.get&#xff08;char&#xff09;进行补救 使用下面这句代码替换掉cin >> ch;,这样就会回显空格&#xff1b; cin.get(ch);//读取输入中的下一个字符&#xff08;即使它是空格&…

LeetCode——二叉树片(七)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 617. 合并二叉树 700. 二叉搜索树中的搜索 98. 验证二叉搜索树 530. 二叉搜索树的最小绝对差 501. 二叉搜索树中的众数 617. 合并二叉树 给你两棵二叉树&#xff1a; …

leetcode 309. 买卖股票的最佳时机含冷冻期

2023.8.22 本题是买卖股票系列 冷冻期。 由于引入了冷冻期&#xff0c;并且这个冷冻期是在卖出股票才会出现&#xff0c;因此我dp数组设置了四种状态&#xff1a; 状态一&#xff1a;持有股票。状态二&#xff1a;不持有股票&#xff1a; 之前就卖了&#xff0c;所以今天不处…

小区新冠疫情管理系统的设计与实现/基于springboot的小区疫情管理系统

摘要 采用更加便于维护和使用的Java语言&#xff0c;其可拓展性高且更富于表现力&#xff0c;基于mysql数据库、Springboot框架开发的小区新冠疫情管理系统&#xff0c;方便用户查看物资信息、疫苗信息。通过Eclipse来进行网页编程&#xff0c;其方便易用、移植适用性广、更加安…

【JVM】对String::intern()方法深入详解(JDK7及以上)一文搞懂

文章目录 1、什么是intern&#xff1f;2、经典例题解释例1例2例3 1、什么是intern&#xff1f; String::intern()是一个本地方法&#xff0c;它的作用是如果字符串常量池中已经包含一个等于此String对象的字符串&#xff0c;则返回代表池中这个字符串的String对象的引用&#…

JVM——类加载与字节码技术—类文件结构

由源文件被编译成字节码文件&#xff0c;然后经过类加载器进行类加载&#xff0c;了解类加载的各个阶段&#xff0c;了解有哪些类加载器&#xff0c;加载到虚拟机中执行字节码指令&#xff0c;执行时使用解释器进行解释执行&#xff0c;解释时对热点代码进行运行期的编译处理。…

每日一题:leetcode 849 到最近的人的最大距离

给你一个数组 seats 表示一排座位&#xff0c;其中 seats[i] 1 代表有人坐在第 i 个座位上&#xff0c;seats[i] 0 代表座位 i 上是空的&#xff08;下标从 0 开始&#xff09;。 至少有一个空座位&#xff0c;且至少有一人已经坐在座位上。 亚历克斯希望坐在一个能够使他与…

同步、异步无障碍:Python异步装饰器指南

一、引言 Python异步开发已经非常流行了&#xff0c;一些主流的组件像MySQL、Redis、RabbitMQ等都提供了异步的客户端&#xff0c;再处理耗时的时候不会堵塞住主线程&#xff0c;不但可以提高并发能力&#xff0c;也能减少多线程带来的cpu上下文切换以及内存资源消耗。但在业务…

2023前端面试题整理

前端面试大全整理 算法 n维数组旋转 90 度算法 export const rotate function (matrix: number[][]) {let n matrix.length// matrix[x][y] > matrix[y][n - 1 - x]const changeItem (num: number, x: number, y: number, rodateTime: number, isOnce?: boolean) >…

微信小程序裁剪图片成圆形

概述 分装的图片剪裁组件&#xff0c;可以把图片剪裁成圆形&#xff0c;主要思路就是使用canvas绘图&#xff0c;把剪裁的图片绘制成圆形&#xff0c;另外剪裁图片的窗口还可以移动放大缩小 详细 前言 最近在开发小程序&#xff0c;产品经理提了一个需求&#xff0c;要求微…

Java Web项目中spring.xml或springmvc.xml配置文件中出现名称空间爆红

在做项目的过程中&#xff0c;通常需要配置spring.xml或者springmvc.xml等配置文件&#xff0c;但是会出现名称空间爆红的情况&#xff0c;如下所示&#xff1a; 解决方法&#xff1a;打开Settings ——> Schemas and DTDs 然后添加爆红的语句即可