【集合简单概述】

并查集是一种处理不相交集合合并和查询的数据结构,常用树形结构表示,支持查找和合并操作。路径压缩是优化查找效率的关键。Hash表用于解决冲突,而STL提供了有序集合(set)和无序集合(unordered_set)等实现,各有其性能特点和适用场景。
摘要由CSDN通过智能技术生成
  • 并查集

1.1并查集主要是处理一些不相交集合的合并和查询的问题。不相交集合,顾名思义,就是两个集合的交集为空集的一些集合

使用并查集时,首先会存在一组不相交的动态集合 S=(S1,S2.·,Sk),一般都会使用一个整数表示集合中的一个元素。

每个集合可能包含一个或多个元素,并选出集合中的某个元素作为代表。每个集合中具体包含了哪些元素是不关心的具体选择哪个元素作为代表一般也是不关心的。我们关心的是,对于给定的元素,可以很快的找到这个元素所在的集合(的代表),以及合并两个元素所在的集合,而且这些操作的时间复杂度都是常数级。

1.2基本操作

所以说对于并查集,主要就是有如下的操作:

1、建立一个新的并查集,其中包含5个单元素集合

2、合并集合,把元素x和元索y所在的集合合并,要求x和y所在的集合不相交,如果相交就不合并。

3、找到元素x所在的集合的代表,这个操作也可以用于判断两个元素是否位于同一集合,只要将他们各自的代表比较一下就可以了。

1.3树的表现形式

并查集的实现原理也比较简单,就是用树来表示一个集合,树的每个结点都是集合的一个元素,树根对应的那个结点就是该集合的代表。

1.4查找

查找操作就是找到的祖先直接返回.

1.5合并

比如我们合并 (4,3), (3,2),(2,1)。如果此时我们合并了一万个结点,这个时候,其实从时间复杂度来说,查找的次数就非常非常多了。

这个时候,我们就想出来了一个策略,路径压缩。

1.6路径压缩

就是在每次查找时,令查找路径上的每个节点都直接指向根节点。

  • Hash表

使用链表(或std::vector等结构)将Hash冲突的元素保存起来。这样,查找一个元素时只需要与Hash冲突的较少元素进行比较。

用这种方式可以完全解决Hash冲突问题。

但是查找元素的复杂度会有所上升(取决于Hash冲突的次数)。

vector<longlong>hash[maxh];

//以下是插入集合的方式,查找也是类似

voidintinsert(x){

inth=f(x);

//计算哈希值

for(inti==0,sz=hash[h].size();i<sz;i++)

if(x==hash[h][i])//从数组中找到了这一项

return;//什么都不做退出

hash[h].push_back(x);//插入这个元素

}

另一种解决方式是将映射푓调整为高维,例如同时使用两个模数:此时,只有当多个Hash函数值同时相等才会导致Hash冲突。冲突概率大幅降低。注意MultiHash对空间的开销较大,因为需要使用二维数组。

  • STL中的集合

STL中也有集合的实现,分为无序集和偏序集。其中分为集合(set)和映射(map)。

无序集在STL中是unordered_set和unordered_map。

其本质为Hash表,因此增删改查均为O(1)。

对于复杂数据类型,需要手动实现Hash函数。

偏序集在STL中是set和map。

本质为排序树(将来介绍),增删改查均为O(logn)。

对于复杂数据类型,需要手动实现偏序关系,即<运算符。

集合在STL中有两种,分别是有序集合和无序集合

需头文件<unordered_set>

需头文件<set>

unordered_set的行为(无序):

set的行为(有序):

功能上类似,但有序集可找前驱后继

unordered_set<Type>s;//创建Type类型的集合

s.insert(x);

//插入元素x

s.erase(x);

//删除值为x的元素

s.erase(it);

//删除it所指的元素

s.end();

//返回末位哨兵的迭代器

s.find(x);

//查询x;不存在则返回s.end()

s.empty();

//判断是否为空

s.size();

//返回集合的大小

set<Type>s;

//创建一个Type类型的集合

s.insert(x);

//插入元素x

s.erase(x);

//删除值为x的元素

s.erase(it);

//删除it所指的元素

s.end();

//返回末位哨兵的迭代器

s.find(x);

//查询x;不存在则返回s.end()

s.empty();

//判断是否为空

s.size();

//返回集合的大小

s.upper_bound(x);

//查询大于x的最小元素

s.lower_bound(y);

//查询不小于x的最小元素

//使用方法与二分查找一

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值