数据结构--并查集

devtools/2024/11/24 1:31:22/

并查集

  • 原理
  • 实现

原理

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。此后我们可能要反复用到查询某一个元素归属于那个集合的运算,适合于描述这类问题的抽象数据类型称为并查集。

并查集的本质就是一个森林,属于同一个集合的元素在同一颗树中,我们可以采用一个数组来描述这个森林:数组下标对应元素的编号,该下标对应的数组值表示该元素的父亲节点的下标,如果为负值-1,表示当前元素是根节点。

开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并,为了查询效率,应该在合并时让数据量小的集合向数据量大的集合合并(这样就是让数据量小的树的元素高度增加,而数据量大的树的元素的高度不变),同时为了避免某棵树的高度过高,我们还需要进行路径压缩,可以选择在查询某个元素时直接将该元素连接到根节点下面,这样下次查询时速度就很快了。

我们这里实现时数组的下标对应的是元素的编号,而我们原本的数据类型是不确定的,因此我们需要将原来的数据类型映射到数组下标上:只需要将数据插入到一个数组当中,这样原始数据就具有了下标,同时我们还可以通过下标直接找到原始数据;为了还可以通过原始数据找到下标,我们可以通过关联式容器map建立原始数据到其下标的映射。

实现

#include<iostream>
#include<map>
#include<vector>
#include<string>using namespace std;template<class T>
class unionFindSet {
public:unionFindSet(vector<T>& datas):_elements(datas),_union(datas.size(),-1){int i = 0;for (; i < _elements.size(); ++i) {_index.insert(make_pair(_elements[i], i));}}~unionFindSet(){}//检查2个元素是否在同一个集合当中bool IsInOneSet(T data1, T data2) {int root1 = FindRoot(data1);int root2 = FindRoot(data2);if (-1 == root1 || -1 == root2) {return false;}return root1 == root2;}//合并2个集合bool Union(T data1, T data2) {int root1 = FindRoot(data1);int root2 = FindRoot(data2);if (-1 == root1 || -1 == root2) {return false;}_union[root1] = root2;return true;}//查找集合的个数int Count() {int ans = 0;for (auto e : _union) {if (-1 == e) {++ans;}}return ans;}
private://返回元素data的根节点int FindRoot(T& data) {if (_index.end() == _index.find(data)) {return -1;}int pos = _index[data];while (-1 != _union[pos]){pos = _union[pos];}if (pos != _index[data]) {//将该元素连接到根节点下面_union[_index[data]] = pos;}return pos;}private:vector<int> _union;				//集合vector<T> _elements;			//将原始数据和下标建立关系的数组map<T, int> _index;	//利用原始数据寻找它在_elemrnts中的下标的关联式容器
};int main() {vector<string> elements = { "alice","bob","jone","jason","tom","jerry","willon","michael" };unionFindSet<string> s(elements);printf("count: %d\n", s.Count());printf("is %s and %s in one set:%d\n", "alice", "bob", s.IsInOneSet("alice", "bob"));s.Union("alice", "bob");printf("is %s and %s in one set:%d\n", "alice", "bob", s.IsInOneSet("alice", "bob"));printf("count: %d\n", s.Count());printf("is %s and %s in one set:%d\n", "alice", "tom", s.IsInOneSet("alice", "tom"));s.Union("alice", "tom");printf("is %s and %s in one set:%d\n", "tom", "bob", s.IsInOneSet("tom", "bob"));printf("count: %d\n", s.Count());return 0;
}

http://www.ppmy.cn/devtools/136426.html

相关文章

flink学习(1)——standalone模式的安装

1、上传&#xff0c;解压&#xff0c;重命名&#xff0c;配置环境变量 将文件上传到/opt/modules下cd /opt/modules tar -zxf flink-1.13.6-bin-scala_2.11.tgz -C /opt/installs/mv flink-1.13.6/ flinkvi /etc/profile export FLINK_HOME/opt/installs/flink export PATH$PA…

Failed to start Docker Application Container Engine

说明&#xff1a; 1&#xff09;访问应用业务&#xff0c;读取不到数据&#xff0c;show databases;查看数据库报错 2&#xff09;重启docker服务&#xff0c;服务启动失败&#xff0c;查看日志报错如下图所示 3&#xff09;报错信息&#xff1a;chmod /data/docker: read-only…

数据结构之树与二叉树

华子目录 1.树和二叉树的定义1.1树的定义1.2树的基本术语1.3线性结构和树结构1.4二叉树的定义 2.二叉树的性质和存储结构2.1二叉树的性质2.2二叉树的存储结构2.2.1顺序存储2.2.2链式存储 2.3遍历二叉树2.4大作业&#xff1a;二叉树的基本操作2.4.1代码思路&#xff08;仅供参考…

[js] 0.1+0.2

0.10.2≠0.3?? 无可避免的浮点误差 【前端面试】为什么 0.1 0.2 不等于 0.3 计算机是通过二进制的方式存储数据的&#xff0c;所以计算机计算 0.1 0.2 的时候&#xff0c;实际上是计算的两个数的二进制的和。0.1 的二进制是0.0001100110011001100…&#xff08;1100 循环&…

计算机毕业设计 | SpringBoot+vue汽车资讯网站 汽车购买咨询管理系统(附源码+论文)

1&#xff0c;绪论 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理汽车资讯网站的相关信息成为必然…

深度解析FastDFS:构建高效分布式文件存储的实战指南(上)

文章目录 一、FastDFS简介1.1 概述1.2 特性 二、FastDFS原理架构2.1 FastDFS角色2.2 存储策略2.3 上传过程2.4 文件同步2.5 下载过程 三、FastDFS适用场景四、同类中间件对比4.1 FastDFS和集中存储方式对比4.2 FastDFS与其他文件系统的对比 五、FastDFS部署5.1 单机部署5.1.1 使…

xiaolin coding 图解网络笔记——HTTP篇

1. HTTP 是什么&#xff1f; HTTP 是超文本传输协议&#xff08;HyperText Transfer Protocol&#xff09;&#xff0c;一个用在计算机世界里专门在【两点】之间【传输】文字、图片、音频、视频等【超文本】数据的【约定和规范】。 2. HTTP 常见的状态码有哪些&#xff1f; …

内容分发网络CDN、动态内容缓存简介

概述 CDN&#xff0c;Content Delivery Network&#xff0c;内容分发网络。使用户可就近取得所需内容&#xff0c;解决网络拥挤状况&#xff0c;提高用户访问网站的响应速度。CDN更智能的镜像缓存流量导流。 核心功能&#xff1a; 加速静态资源加载&#xff08;如图片、视频…