高阶数据结构:并查集

news2024/11/15 6:39:48

本篇主要是介绍并查集的内容:所谓并查集就是一种描述不相交集合的数据结构,即若一个问题涉及多个元素,它们可以划分到不同集合,同属一个集合内的元素等价,不同集合内的元素不等价。


文章目录

  • 一、并查集原理
  • 二、并查集实现
  • 三、并查集应用

一、并查集原理

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

如下图所示:

 结论:1、数组下标对应集合中元素的编号。

            2、数组中如果为负数,负数代表根,数字代表该集合中元素的个数。

            3、数组中如果为非负数,代表该元素双亲在数组中的下标。

如果其中两棵树变成棵树的情况,如下图所示:

 通过上面的两张图片可以知道:并查集一般可以解决:

1、查找元素属于哪个集合(沿着数组表示树形关系以上一直找到根(即树中元素为负数的位置)。

2、查看两个元素是否属于同一个集合(沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在)。

3、将两个集合归并成一个集合(将两个集合中的元素合并,将一个集合名称改成另一个集合的名称) 。

4、集合的个数(遍历数组,数组中元素为负数的个数即为集合的个数)。

二、并查集实现

#include<iostream>
#include<vector>

using namespace std;

class UnionFindSet
{
public:
	//初始化:将数组中元素全部设置为1
	UnionFindSet(int size)
		:_ufs(size, -1)
	{}

	//给数组元素一个编号,找到该元素所在集合的名称
	size_t FindRoot(int x)
	{
		while (_ufs[x] >= 0)
			x = _ufs[x];
		return x;
	}

	//合并两个集合
	void Union(int x1, int x2)
	{
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);

		if (root1 != root2)
		{
			_ufs[root1] += _ufs[root2];
			_ufs[root2] = root1;
		}
	}

	//找出并查集中根的个数
	size_t SetCount()
	{
		size_t count = 0;
		for (int i = 0; i < _ufs.size(); i++)
			if (_ufs[i] < 0)
				count++;
		return count;
	}
private:
	vector<int> _ufs;
};
int main()
{
	UnionFindSet ufs(10);

	ufs.Union(0, 6);
	ufs.Union(0, 7);
	ufs.Union(0, 8);
	
	ufs.Union(1, 4);
	ufs.Union(1, 9);

	ufs.Union(2, 3);
	ufs.Union(2, 5);

	cout << ufs.SetCount() << endl;
}

三、并查集应用

        1.省份的数量OJ链接

 

/*class UnionFindSet
{
public:
    UnionFindSet(size_t n)
    :_ufs(n,-1)
    {}
   size_t FindRoot(int x)
   {
       while(_ufs[x]>=0)
            x=_ufs[x];
        return x;
   }
   void Union(int x1,int x2)
   {
       int root1=FindRoot(x1);
       int root2=FindRoot(x2);

       if(root1!=root2)
       {
           _ufs[root1]+=_ufs[root2];
           _ufs[root2]=root1;
       }
   }

   size_t SetCount()
   {
       size_t count=0;
       for(int i=0;i<_ufs.size();i++)
            if(_ufs[i]<0)
                count++;
        return count;
   }
private:
   vector<int> _ufs;
};
class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        
        //手动创建一个并查集
        UnionFindSet ufs(isConnected.size());

        //如果此时isConnected[i][j]==1说明第i个和第j个城市直接相连,可以认为二者是在同一棵树中
        for(int i=0;i<isConnected.size();i++)
            for(int j=0;j<isConnected[i].size();j++)
                if(isConnected[i][j]==1)
                    ufs.Union(i,j);

        return ufs.SetCount();
    }
};*/
class Solution {
public:
    size_t FindRoot(vector<int>&_ufs,int x)
    {
        while(_ufs[x]>=0)
            x=_ufs[x];
        return x;
    }
    int findCircleNum(vector<vector<int>>& isConnected) {
        vector<int> _ufs(isConnected.size(), -1);
        
        for(int i=0;i<isConnected.size();i++)
        {
            for(int j=0;j<isConnected[0].size();j++)
            {
                if(isConnected[i][j]==1)
                {
                    int root1=FindRoot(_ufs,i);
                    int root2=FindRoot(_ufs,j);

                    if(root1!=root2)
                    {
                        _ufs[root1]=_ufs[root2];
                        _ufs[root2]=root1;
                    }
                }
            }
        }

        int count=0;
        for(int i=0;i<_ufs.size();i++)
            if(_ufs[i]<0)
                count++;

        return count;
    }
};

         2.等式方程的可满足性OJ链接

 

 

class Solution {
public:
    size_t FindRoot(vector<int>&ufs,int x)
    {
        while(ufs[x]>=0)
            x=ufs[x];
        return x;
    }
    bool equationsPossible(vector<string>& equations) {
        vector<int> _ufs(26,-1);

        //第一遍是将所有的变量之间相等的放入同一个集合中
        for(auto&str:equations)
        {
            if(str[1]=='=')
            {
                int root1=FindRoot(_ufs,str[0]-'a');
                int root2=FindRoot(_ufs,str[3]-'a');

                if(root1!=root2)
                {
                    _ufs[root2]+=_ufs[root1];
                    _ufs[root1]=root2;
                }
            }
        }

        //第二遍是讲不等的变量如果出现在同一个集合中则直接返回false
        for(auto&str:equations)
        {
            if(str[1]=='!')
            {
                int root1=FindRoot(_ufs,str[0]-'a');
                int root2=FindRoot(_ufs,str[3]-'a');

                if(root1==root2)
                    return false;
            }
        }

        return true;
        
    }
};

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

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

相关文章

Prophet在R语言中进行时间序列数据预测

您将学习如何使用Prophet&#xff08;在R中&#xff09;解决一个常见问题&#xff1a;预测公司明年的每日订单。 最近我们被客户要求撰写关于时间序列的研究报告&#xff0c;包括一些图形和统计输出。 数据准备与探索 Prophet最适合每日数据以及至少一年的历史数据。 我们将…

Ansible

Ansible是什么&#xff1f; Ansible是一个基于eythn开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pbet和Saltstack能实现的功能&#xff0c;As;ble基本上都可以实现。Ansible能批量配置、部署、管理上…

MongoDB入门与实战-第五章-MongoDB副本集

目录参考一、副本集概念1、**主要功能**2、主从复制和副本集区别3、复制结构图二、副本集成员角色1.主节点2.副本节点3.仲裁节点三、副本集架构&#xff08;一主一副本一仲裁&#xff09;1、**设置读操作权限&#xff1a;**2、取消作为奴隶节点的读权限四、选举原则1、触发条件…

时序逻辑电路

数字电路分为两大类&#xff0c;组合逻辑电路和时序逻辑电路 今天我们要开始学习的是时序逻辑电路&#xff0c;要求大家掌握 同步逻辑电路的分析方法 常用的时序逻辑电路的使用方法 当然由于时序逻辑电路的特点&#xff0c;使得时序逻辑电路难度远远大于组合逻辑电路 电路任…

一文详解Redis键过期策略,最全文档

文章目录1 设置带过期时间的 key1.1 刷新过期时间1.2 Redis 之前的 2.1.3 的差异1.3 返回值1.4 示例1.5 带过期时间的 key1.6 过期精度1.7 过期和持久化2 Redis的key过期策略2.1 惰性删除2.1.1 优点2.1.2 缺点定时删除优点缺点2.2 定期删除优点缺点难点定期删除流程Redis采用的…

SpringMVC异常处理器

1.异常 1.1 异常结构层次 异常主要分为&#xff1a;错误、一般性异常&#xff08;检查异常&#xff09;、运行期异常&#xff08;非受控异常&#xff09; 错误&#xff1a;如果应用程序出现了 Error&#xff0c;那么将无法恢复&#xff0c;只能重新启动应用程序&#xff0c;最…

VUE3-工作笔记-06

本节&#xff1a;总结11月份学习的内容 1.如果有很多个功能是一样的&#xff0c;那就先写一个测试很多次&#xff0c;确定没有bug再全部改&#xff0c;不然辛辛苦苦全部改了之后&#xff0c;发现还是有bug又要重新改&#xff0c;最好是写成组件的形式&#xff0c;写成hook。 …

ACM第三周---周训---题目合集.

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石.CSDN &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​ &#x1f4e3;系列专栏&#xff1a;ACM周训练题目合集.CSDN &#x1f4ac;总结&#xff1a…

微服务框架 SpringCloud微服务架构 10 使用Docker 10.7 数据卷命令

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构10 使用Docker10.7 数据卷命令10.7.1 数据卷10.7.2 操作数据卷10.7.3 直接…

度量方法总结

本文目录0 引言1 度量差异性1.1 闵可夫斯基距离&#xff08;Minkowski distance&#xff09;1.1.1 欧氏距离&#xff08;Euclidean distance&#xff09;1.1.2 曼哈顿距离&#xff08;Manhattan distance&#xff09;1.1.3 切比雪夫距离&#xff08;Chebyshev distance&#xf…

[附源码]JAVA毕业设计课程网站设计(系统+LW)

[附源码]JAVA毕业设计课程网站设计&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

Spring Boot 框架整合 MyBatis 连接数据库,详细说明

在我们日常的开发过程中&#xff0c;肯定不可避免的会使用到数据库以及 SQL 语句。比如&#xff0c;刚开始学习 Java 的时候可能会遇到 JDBC&#xff0c;它是连接 Java 和数据库的桥梁&#xff0c;我们可以使用 JDBC 来建立与数据库之间的连接并且执行相应的 SQL 语句。虽然 JD…

数据结构—List集合

文章目录一、ArrayList集合1&#xff0c;ArrayList集合的特点2&#xff0c;ArrayList集合的一些方法添加元素个数获取指定位置元素指定位置插入元素替换元素移除元素判断是否为空判断是否包含元素移除指定元素迭代器遍历集合二、LinkedList集合1&#xff0c;LinkedList集合的特…

Ra-01SC/Ra-01SCH模组驱动

目录简介硬件准备设备清单接线说明重要函数说明调试联系我们简介 本文档主要介绍Ra-01SC/Ra-01SCH模组驱动例程使用方法&#xff1b; 硬件准备 设备清单 硬件数量Ra-001SC/Ra-01SCH 模组2个杜邦线若干USB转TTL模块2个STM32F103C8T6开发板2个安卓线2根 接线说明 STM32F103C…

[论文阅读] 颜色迁移-直方图渐进式颜色迁移

[论文阅读] 颜色迁移-直方图渐进式颜色迁移 文章: 有2篇相关的文章, 都为同一作者 [Progressive histogram reshaping for creative color transfer and tone reproduction], [code未公开][Progressive color transfer for images of arbitrary dynamic range], [code未公开]…

qt模块feature QT_FEATURE_* qt_lib_*.pri QT_CONFG qtConfig

qt为方便对代码进行删减&#xff0c;将代码拆分成很多模块&#xff0c;对每个模块梳理出feature&#xff0c;为了简化程序的使用和其他目的&#xff0c;qt还对每个模块分成public模块和private模块&#xff08;比如core分为core和core-privare模块&#xff0c;但两者公用同一个…

迭代器失效问题

目录 一、vector迭代器失效问题 1、resize,reserve,insert,assign,push_back可能引起底层空间改变 2、指定位置元素的删除操作erase 3、Linux下&#xff0c;g编译器对迭代器失效的检测不是非常严格&#xff0c;处理也没有vs下极端 4、与vector类似&#xff0c;string在插入…

java swing(GUI) MySQL实现的飞机票预定系统源码带视频运行教程

大家好&#xff0c;今天给大家演示一下由Java swing实现的飞机票预定系统&#xff0c;系统数据库原本采用的是Oracle&#xff0c;我又改了一个mysql版本的&#xff0c;所以这套系统有两个版本&#xff0c;一个是mysql数据库版的&#xff0c;一个是Oracle数据库版&#xff0c;演…

TypeScript是强类型,静态类型的Java Script

1. 编程语言的分类 As we all know, JavaScript 是弱类型&#xff0c;动态类型的编程语言。 首先我们来解释一下这几个名词&#xff1a; 动态类型语言&#xff1a;在 运行期间(Runtime) 才去做数据类型检查的语言。静态类型语言&#xff1a;在 编译其间(Compile) 就进行数据…

【Redis】事务秒杀案例

一、背景 在日常购物时&#xff0c;经常会有商家开展限时秒杀活动&#xff0c;我们如何使用redis来实现这种场景呢 二、业务代码 首先我们可以想到的是&#xff0c;我们可以把商品剩余数量和成功秒杀商品的用户id放在redis中 下面是我们的业务代码 package com.decade.con…