专栏文章

STL整理之set

算法·理论参与者 50已保存评论 56

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
56 条
当前快照
1 份
快照标识符
@mhz5tbda
此快照首次捕获于
2025/11/15 01:56
4 个月前
此快照最后确认于
2025/11/29 05:25
3 个月前
查看原文
转载请注明出处,部分内容引自李煜东《算法竞赛进阶指南》

前置知识: C++C++CC语言入门


SetSet是什么

SetSetC++STLC++STL中提供的容器,setset是数学上的集合——具有唯一性,即每个元素只出现一次,而multisetmultiset则是可重集,两者的内部实现是一棵红黑树,它们支持的函数基本相同


SetSet的相关操作

头文件

CPP
#include<set>

声明:

像这样:
CPP
set<类型>名称;
比如:
CPP
set<int>s;
set<vector<int> >s;		//vector中提供重载<
set<set<int> >s;	//平衡树嵌套,哈哈
multiset<double>s;
就像其他需要排序的数据类型一样,为一个结构体的setset,需要重载小于号
CPP
struct node{
    ......;
};
set<node>s;
bool operator <(const node &ai,const node &bi)
{
	return ai.x>bi.x;
}

set.size()set.size()

统计setset中元素个数,函数返回一个整形变量,表示setset中元素个数,时间复杂度O(1)
CPP
用法:名称.size();
eg.
int num=s.size();

set.empty()set.empty()

检查setset是否为空,返回一个boolbool型变量,1表示setset为空,否则为非空,时间复杂度O(1)O(1)
CPP
用法:名称.empty();
eg.
if(s.empty())
	cout<<"Myset is Empty."<<endl;

set.clear()set.clear()

清空setset,无返回值
CPP
用法:名称.clear();
eg.
s.clear();

set.count(x)set.count(x)

返回setsetmultisetmultiset中值为xx的元素个数,时间复杂度为O(logn+ans)O(log n+ans)
CPP
用法:名称.count(x)
eg.
if(!s.count(x))
	ans++;

迭代器

双向访问迭代器,不支持随机访问,支持星号解除引用,仅支持“++”,“--”这两个算术操作

引用和操作:
CPP
set<类型>::iterator it;
eg.
set<int>::iterator it=s.begin();
it++;
it--;
若把it++it++,则itit将会指向“下一个”元素。这里的下一个是指在keykey从小到大排序的结果中,排在itit下一名的元素。同理,若把itit--,则itit会指向排在上一个的元素
“++”,“--”操作的复杂度均为O(logn)O(log n)

遍历setset及访问其中的元素

CPP
//set
for(set<int>::iterator it=s.begin();it!=s.end();it++)
    cout<<*it<<endl;	//取出这个迭代器指向的元素
//set嵌套
for(set<set<int> >::iterator it=s.begin();it!=s.end();it++)
{
	//首先取出set中嵌套的set
    for(set<int>::iterator rit=(*it).begin();rit!=(*it).end();rit++)
        cout<<*rit<<' ';	//遍历这个set
    cout<<endl;
}

set.begin()set.begin()

返回集合的首迭代器,即指向集合中最小元素的迭代器,时间复杂度为O(1)O(1)
CPP
用法:名称.begin();
eg.
set<int>::iterator it=s.begin();

set.end()set.end()

返回集合的尾迭代器,众所周知,STL中区间都是左闭右开的,那么end()end()函数返回的迭代器即为指向集合中最大元素的下一个位置的迭代器,因此s.end()--s.end()才是指向集合中最大元素的迭代器,时间复杂度为O(1)O(1)
CPP
用法:名称.end();
eg.
maxn=*(--s.end());		//取出最大元素

set.insert(x)set.insert(x)

setset中插入元素,返回插入地址的迭代器和是否插入成功的boolbool并成的pairpair,时间复杂度为O(logn)O(log n)
PS:setset在进行插入的时候是不允许有重复的键值的,如果新插入的键值与原有的键值重复则插入无效(multisetmultiset可以重复)
CPP
用法:名称.insert(set类型);
eg.
s.insert(3);

set.erase(set.erase(参数))

删除,参数可以是元素或者迭代器,返回下一个元素的迭代器,时间复杂度为O(logn)O(log n),注意在multisetmultisets.erase(x)s.erase(x)会删除所有值为xx的元素
CPP
用法:名称.erase(参数);
eg.
set<int>::iterator it=s.begin();
s.erase(it);
s.erase(3);

set.find(x)set.find(x)

setset中查找值为xx的元素,并返回指向该元素的迭代器,若不存在,返回set.end()set.end(),时间复杂度为O(logn)O(log n)
CPP
用法:名称.find(x);
eg.
if(s.find(x)!=s.end())
	cout<<"Have Found!"<<endl;

set.lowerset.lowerbound(x)/upperbound(x)/upperbound(x)bound(x)

两个神奇的东西,决定把他们放在一块谈一谈
用法与findfind类似,但查找的条件略有不同,时间复杂度O(logn)O(log n)
s.lowers.lower_bound(x)bound(x)表示查找>=x>=x的元素中最小的一个,并返回指向该元素的迭代器
s.uppers.upper_bound(x)bound(x)表示查找>x>x的元素中最小的一个,并返回指向该元素的迭代器

举个例子:

setset{3,5,7,8,13,163,5,7,8,13,16}中
对于在setset中存在的元素,比如8
s.lowers.lower_bound(8)bound(8)返回8所在位置的迭代器
s.uppers.upper_bound(8)bound(8)返回13所在位置的迭代器
对于在setset中不存在的元素,比如12
两个函数返回的则都是13所在位置的迭代器

特殊地,

对于比setset中最大的元素大的元素,比如20
两个函数返回的都是s.end()s.end()

评论

56 条评论,欢迎与作者交流。

正在加载评论...