C++ STL之set详解

本文章已经生成可运行项目,

返回STL主目录

7 set

7.1 介绍

set容器中的元素不会重复,当插入集合中已有的元素时,并不会插入进去,而且set容器里的元素自动从小到大排序。

即:set里面的元素不重复 且有序

//头文件
#include<set>
//初始化定义
set<int> s;
  • 拷贝初始化
set<int> a = {1, 3, 5}; // 初始化指定元素
set<int> b(a);
// set<int> b = a; // b和a一样,同样是拷贝初始化

7.2 函数方法

代码复杂度含义
s.begin() O ( 1 ) O(1) O(1)返回set容器的第一个元素的地址(迭代器)
s.end() O ( 1 ) O(1) O(1)返回set容器的最后一个元素的下一个地址(迭代器)
s.rbegin() O ( 1 ) O(1) O(1)返回逆序迭代器,指向容器元素最后一个位置
s.rend() O ( 1 ) O(1) O(1)返回逆序迭代器,指向容器第一个元素前面的位置
s.clear() O ( N ) O(N) O(N)删除set容器中的所有的元素,无返回值
s.empty() O ( 1 ) O(1) O(1)判断set容器是否为空
s.insert(element) O ( l o g N ) O(logN) O(logN)插入一个元素
s.size() O ( 1 ) O(1) O(1)返回当前set容器中的元素个数
erase(iterator) O ( l o g N ) O(logN) O(logN)删除定位器iterator指向的值
erase(first, second)删除定位器first和second之间的值
erase(key_value) O ( l o g N ) O(logN) O(logN)删除键值key_value的值
查找
s.find(element)查找set中的某一元素,有则返回该元素对应的迭代器,无则返回结束迭代器
s.count(element)查找set中的元素出现的个数,由于set中元素唯一,此函数相当于查询element是否出现
s.lower_bound(k) O ( l o g N ) O(logN) O(logN)返回大于等于k的第一个元素的迭代器
s.upper_bound(k) O ( l o g N ) O(logN) O(logN)返回大于k的第一个元素的迭代器

7.3 元素访问

  • 迭代器访问
for(set<int>::iterator it = s.begin(); it != s.end(); it++)
	cout << *it << " ";
  • 智能指针
for(auto i : s)
	cout << i << endl;
  • 访问最后一个元素
//第一种
cout << *s.rbegin() << endl;
 //第二种
set<int>::iterator iter = s.end();
iter--;
cout << (*iter) << endl; //打印2;
//第三种
cout << *(--s.end()) << endl;

7.4 重载<运算符

  • 基础数据类型

方式一:改变set排序规则,set中默认使用less比较器,即从小到大排序。(常用)

set<int> s1; // 默认从小到大排序
set<int, greater<int> > s2; // 从大到小排序

方式二:重载运算符。(很麻烦,不太常用,没必要)

//重载 < 运算符
struct cmp {
    bool operator () (const int& u, const int& v) const {
       // return + 返回条件
       return u > v;
    }
};
set<int, cmp> s; 

for(int i = 1; i <= 10; i++)
    s.insert(i);
for(auto i : s)
    cout << i << " ";
// 10 9 8 7 6 5 4 3 2 1

方式三:初始化时使用匿名函数定义比较规则

set<int, function<bool(int, int)>> s([&](int i, int j){
    return i > j; // 从大到小
});
for(int i = 1; i <= 10; i++)
    s.insert(i);
for(auto x : s)
    cout << x << " ";
  • 高级数据类型(结构体)

直接重载结构体运算符即可,让结构体可以比较。

struct Point {
	int x, y;
	bool operator < (const Point &p) const {
		// 按照点的横坐标从小到大排序,如果横坐标相同,纵坐标从小到大
		if(x == p.x)
			return y < p.y;
		return x < p.x;
	}
};

set<Point> s;
for(int i = 1; i <= 5; i++) {
    int x, y;
    cin >> x >> y;
    s.insert({x, y});
}	
/* 输入
5 4
5 2
3 7
3 5
4 8
*/

for(auto i : s)
    cout << i.x << " " << i.y << "\n";
/* 输出
3 5
3 7
4 8
5 2
5 4
*/

7.5 multiset

multiset :元素可以重复,且元素有序

  • 注意点一:方法函数基本和 set 一样,参考set即可。

  • 注意点二:进行删除操作时,要明确删除目标。( s 为声明的multiset变量名)

    删除多个元素:由于元素可以重复,注意使用 s.erase(val) 方法时,会删除掉所有与 val 相等的元素

    删除一个元素:需要删除一个元素时,需要使用 s.erase(s.find(val)) 操作,先找到一个与 val 相等的元素迭代器,专门删除这个元素

  • 注意点三:头文件操作为 #include<set>

unordered_set :元素无序且只能出现一次

unordered_multiset :元素无序可以出现多次

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行码棋

码字好辛苦,总结好吃力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值