STL专题-set 集合
本文最后更新于:2021年3月4日 下午
STL中set集合、multiset集合、unordered_set的用法。
set——集合
头文件 #include <map>
- set,是一种关联式容器,底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。容器中的数据不能重复,即每个数据都是唯一的,并且会对存进去的数据进行自动升序排序。
- 此外不能够通过set的迭代器修改set元素的值,因为其本身就是键值,任意改变会破坏set的组织结构。
- 构造set集合的主要目的是为了快速检索,去重与排序。
set函数
1 |
|
set基本操作
创建set对象
1 |
|
- set容器默认是从小到大进行排序,
set<int,myComp> a;
可通过这种方式来修改其默认的排序规则。具体实现看:自定义排序那一小节。 - 对于自定义数据类型的set,必须在模板参数列表这里指定自定义的排序规则,否则编译器不知道该怎么插入。
添加元素 insert
insert(value); 将某一值插入set中,返回值是 pair<set<int>::iterator,bool>
,即返回插入的位置的迭代器以及是否插入成功。
重复的值是不会被插入的,返回的位置是原先元素的位置,同时bool值为false。
find函数
find(const key_type &key)函数用于查找与key值相同的元素,并返回其位置的迭代器。而如果没有找到将会返回end()指向的迭代器。
迭代器
关联式容器不支持iterator+n的操作,n为1也不行,只能使用iter++这种操作。
顺序遍历
1 |
|
逆序遍历
1 |
|
注意迭代器的写法,反向遍历使用reverse_iterator来定义迭代器,函数使用rbegin()与rend()方法!
pair对组
- pair对组可以创建成对出现的数据,可以用其来返回一对数据。
- pair有两种创建方式,使用默认构造创建或者使用
make_pair()
函数创建。 - 使用
.first
访问第一个数据,.second
访问第二个数据。
1 |
|
自定义排序
- 对于自定义数据类型,必须指定其排序规则,否则无法插入。
set容器在判定已有元素a和新插入元素b是否相等时有以下两个步骤。
将a作为做操作数,b作为右操作数,调用比较函数,并返回比较值。
将b作为做操作数,a作为右操作数,再调用比较函数,并返回比较值。
也就是说,假设有f(x,y)比较函数,先进行f(a,b)然后再进行f(b,a),返回两个bool值。
如果返回值都是false,则认为a、b是相等的,b不会被插入。如果第一个是true,第二个是false,则b要排在a后面,繁殖b要排在a前面。如果返回值都是true,则可能发生未知行为。
- 自定义比较结构体,重载
()
操作符
1 |
|
- 重载
<
操作符
1 |
|
输出结果:
1 |
|
可以看到,重复id会被清除,然后按照从小到大的顺序排序。
set与multiset
二者均使用头文件<set>
。
但是二者的insert()
函数返回值不同,set返回一个对组pair<set<T>::iterator,bool>
,而multiset则直接返回插入位置的迭代器。
- 如果不允许插入重复数据可以利用set。
- 如果需要插入重复数据利用multiset。
unordered_set 无序集合
头文件:#include <unordered_set>
底层实现:哈希表,插入结果是无序的,而set则会自动排序。
常用api:insert/find/erase
,find找到返回迭代器,找不到返回end()。
insert/find/erase的平均复杂度是O(1),但是最坏复杂度是O(N)的
蓝桥杯真题——错误票据
题目描述:
某涉密单位下发了某种票据,并要在年终全部收回。每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
要求程序首先输入一个整数N(N<100)表示后面数据行数。
接着读入N行数据。
每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000)
每个整数代表一个ID号。
要求程序输出1行,含两个整数m n,用空格分隔。
其中,m表示断号ID,n表示重号ID
输入:
要求程序首先输入一个整数N(N<100)表示后面数据行数。接着读入N行数据。
每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000)
每个整数代表一个ID号。
输出:
要求程序输出1行,含两个整数m n,用空格分隔。
其中,m表示断号ID,n表示重号ID
样例输入
2
5 6 8 11 9
10 12 9样例输出
7 9
问题分析
题目意思很清楚,将会给出一连串被打乱的数字,数字连续,只是有一个数字重复了两次,这个可以使用set中的insert方法,它会返回一个pair(pair中是迭代器与bool值),通过bool值来进行去重。(见上方insert函数)而找断号的数据进行从头开始遍历判断即可。
另:题目要求输入n行,每行数据不等,采用while(scanf(“%d”,&a)!=EOF)来进行收集数据好一些。
详细参见:蓝桥杯——一些零碎的注意事项
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!