【集合】C++ 数据结构 集合 set

工作也不想做,博客也不想写QAQ又是一个难熬的下午……
这个月的leetcode每日一题落下了好多,主要是动态规划我真不会,看题解基本也想不明白,DP我的一生之敌(x_x)


前言

这里要介绍一下顺序容器和关联容器的区别。顺序容器就是按照元素在容器中的位置,来进行保存和访问,例如vector、deque、list、forward_list、array、string,它们的共同特点是可以快速顺序访问元素;而关联容器中的元素按照关键字来进行保存和访问,例如set和map,因此它们不支持位置相关的操作,但是支持高效的关键字查找和访问。


一、集合是什么?

这里的集合和数学上的集合概念差不多,集合的主要特点有确定性(一个元素只能属于或不属于一个集合),互异性(即任意两个元素互不相同),和无序性(元素之间是无序的)。
而set数据结构的两大特点是

  1. set内部元素自动排序
  2. set内部元素唯一,无重复元素

要注意的是这里的排序是指,在set的内部是按元素值大小进行排序的,与元素的添加顺序无关。

二、定义和初始化

*注意:在使用时需要带头文件#include<set>

set<int> s;
set<int> s {1,2,3,4,5};
set<int> s(s1); //拷贝构造
set<int> s(v.begin(), v.end()); //v可以是同类型一维数组

三、读取数据

前面提到,集合不支持按照位置访问元素,所以一般可以这样读取集合内全部元素

set<int> s {1,3,2,5,4};
for(int i:s)
	cout<<i<<",";  ->1,2,3,4,5,

集合中的元素会按照值大小进行自动排序。set内部采用的是一种非常高效的平衡检索二叉树:红黑树,也称为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树。

四、增删查

*注意:set中元素的值是不能直接被改变的,只能插入删除指定元素。

//插入
s.insert(n);

//删除
s.erase(n); //删除指定元素
s.erase(v.begin(),v.end()); //删除迭代器范围内的元素
s.clear(); //清空集合

//查找
s.count(n) //集合中元素唯一,所以count只能返回0或1,可以判断元素是否存在
s.find(n) //返回一个指向被查找到元素的迭代器

s.size() //求集合大小

五、集合运算

集合运算不止可以对set,还可以对map、vector等进行运算,但前提是两个集合必须按同样的规则排序。set和map本身是有序的,可以直接进行集合运算,而vector则需要提前排序。
*注意:使用集合运算方法时需要带头文件#include<algorithm>

//交集A*B,结果存到集合C中
set_intersection(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));

//并集A+B,结果存到集合C中
set_union(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));

//差集A-B(注意顺序),结果存到集合C中
set_difference(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));

举个栗子:

set<int> A{1,2,3,4,5};
set<int> B{2,4,6,8};
set<int> C;
//求交集
set_intersection(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));  ->{2,4}
C.clear();
//求并集
set_union(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));  ->{1,2,3,4,5,6,8}
C.clear();
//求差集
set_difference(A.begin(),A.end(),B.begin(),B.end(),inserter(C,C.begin()));  ->{1,3,5}

记得存放结果的集合要为空,不然原有的元素还会存在。


总结

集合是一个比较重要的结构,集合运算在一些场景下也非常实用,下次写用法有点类似的哈希表。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值