C++ set 常用部分

文章目录

关键特性

  • 唯一性 :Set容器内的元素都是唯一的 ,每个元素都是不同的
  • 有序性 :Set容器内的元素总是排序的(C++中默认升序),向Set中添加元素,将自动插入到正确的位置中,不需要手动排序
  • 查找/插入快速 :因为Set容器的元素是排序的,所以在Set中查找和插入元素都很快

定义及初始化

cpp 复制代码
#include <set>
set<Type> s;						      
set<int> s = {1,2,3,4,5};	 
vector<int> a = {1,2,3,4,5};
set<int> s(a.begin(),a.end());
set<Type> s(s1);			              //定义一个set容器,并用容器s1来初始化
set<Type> s(b, e);					  //b和e分别为迭代器的开始和结束的标记
set<Type> s(s1.begin(), s1.begin()+3); //用容器s1的第0个到第2个值初始化s
set<Type> s(a, a + 5);      		      //将a数组的元素初始化vec向量
set<Type> s(&a[1], &a[4]); 			  //将a[1]~a[4]范围内的元素作为s的初始值

一些基本操作

cpp 复制代码
s.begin();					//返回指向第一个元素的迭代器
s.end();					//返回指向最后一个元素的迭代器
s.clear();					//清除所有元素
s.count();					//返回某个值元素的个数
s.empty();					//如果集合为空,返回true,否则返回false
s.equal_range();			//返回集合中与给定值相等的上下限的两个迭代器
s.erase();					//删除集合中的元素
s.find(k);					//返回一个指向被查找到元素的迭代器
s.insert();					//在集合中插入元素
s.lower_bound(k);			//返回一个迭代器,指向键值大于等于k的第一个元素
s.upper_bound(k);			//返回一个迭代器,指向键值大于k的第一个元素
s.max_size();				//返回集合能容纳的元素的最大限值
s.rbegin();					//返回指向集合中最后一个元素的反向迭代器
s.rend();					//返回指向集合中第一个元素的反向迭代器
s.size();					//集合中元素的数目

查找

find(x)方法寻找带有特定键的元素,返回的是迭代器。

cpp 复制代码
set<int> s = {1,2,3,4,5};

if(s.find(3)!=s.end())//若存在,返回一个迭代器,指向键值;若不存在,返回一个迭代器,指向s.end()。
	cout<<*s.find(3)<<endl;
else
    cout<<"NOT FOUND"<<endl;

count(x)方法返回的是set中元素x的个数。由于个数只能是0或1,所以当返回值非0时表示元素在集合中,反之不在。

cpp 复制代码
set<int> s = {1,2,3,4,5};

if(s.count(3) > 0)
    cout << s.count(3) << endl;
else
    cout<<"NOT FOUND"<<endl;

插入

cpp 复制代码
//插入一个元素
set<int> s;
s.insert(10);
//插入多个元素
vector<int> array{1, 2, 3};
int a[] = {1,2,3};
set<int> s;
s.insert(array.begin(), array.end()); 
s.insert(a,a+3);
//使用emplace函数插入元素
set<int> s;
s.emplace(10);

删除

语法格式

cpp 复制代码
set_name.erase(element);//删除 set 容器中值为 val 的元素
name.erase(iterator position);//删除 position 迭代器指向的元素
name.erase(iterator start, iterator end);//删除 [start,end) 区间内的所有元素

示例

cpp 复制代码
set<int> myset={1,2,3,4,5};
myset.erase(30);
myset.erase(myset.find(3));
myset.erase(myset.begin(),myset.end())

Reference:

https://vimsky.com/examples/usage/unordered_set-erase-function-in-c-stl.html

https://www.cainiaojc.com/cpp/cpp-set-erase-function.html

https://c.biancheng.net/view/7198.html

https://blog.csdn.net/chenyijun/article/details/119065095

清空

cpp 复制代码
myset.clear();

遍历

迭代器遍历

cpp 复制代码
set<int> myset={1,2,3,4,5};

for(auto it = mySet.begin(); it != mySet.end(); it++)
{
    cout<<*it<<" ";
}
cout<<endl;

for循环新用法

cpp 复制代码
set<int> myset={1,2,3,4,5};
for(auto i : myset){
	cout<<i<<endl;
}

lower_bound()、upper_bound()

lower_bound(key_value) :返回第一个大于等于key_value的定位器

upper_bound(key_value):返回第一个大于key_value的定位器

cpp 复制代码
set<int> s={1,2,3,4,5};

cout<<*s.lower_bound(1)<<" ";
cout<<*s.lower_bound(2)<<" ";
cout<<*s.upper_bound(3)<<" ";

//输出:1 2 4

set与unordered_set的区别

set与unordered_set一样,都是关联式容器,和 map 容器不同,使用 set 容器存储的各个键值对,要求键 key 和值 value 必须相等。

当使用 set 容器存储键值对时,只需要为其提供各键值对中的 value 值(也就是 key 的值)即可。

使用 set 容器存储的各个元素的值必须各不相同

从语法上讲 set 容器并没有强制对存储元素的类型做 const 修饰,即 set 容器中存储的元素的值是可以修改的。但是,C++ 标准为了防止用户修改容器中元素的值,对所有可能会实现此操作的行为做了限制,使得在正常情况下,用户是无法做到修改 set 容器中元素的值的。

主要区别:

set

  • 定义于头文件
  • 底层实现通常是平衡二叉树
  • 元素自动排序,这为查找元素提供了良好性能,但同时也造成了一个重要限制:不能直接改变元素值,因为这会打乱原本正确的顺序
  • 查找函数具有对数复杂度
  • 要改变元素的值,必须先删除该元素,再插入新元素

unordered_set

  • 定义于<unordered_set>头文件
  • 底层实现通常是hash-table
  • 元素是无序的
  • 插入、删除、查找元素的时间复杂度是常量的(排除偶尔的rehashing导致的线性复杂度)

总结

综上,以下情况使用set:

  • 需要排序的数据
  • 需要通过前序、后序等方式遍历元素或者查找前继后继元素
  • 想要使用binary_search(), lower_bound() and upper_bound()等需要在有序元素上使用的方法
  • 其他平衡二叉树具有而hash表没有的优点

在以下情况使用unordered_set:

  • 仅需要保存互异的元素而不需要排序
  • 只需要获取单个元素而不需要遍历

两者的区别参考:

https://zhuanlan.zhihu.com/p/439197313

https://blog.csdn.net/bryant_zhang/article/details/111600209

https://zhuanlan.zhihu.com/p/131009604

reference:

https://blog.csdn.net/weixin_44668898/article/details/102089892

还可以参考:

https://zhuanlan.zhihu.com/p/682656691

相关推荐
感哥1 小时前
C++ 面向对象
c++
CoovallyAIHub3 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
沐怡旸3 小时前
【底层机制】std::shared_ptr解决的痛点?是什么?如何实现?如何正确用?
c++·面试
NAGNIP3 小时前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo4 小时前
半开区间和开区间的两个二分模版
算法
moonlifesudo4 小时前
300:最长递增子序列
算法
CoovallyAIHub9 小时前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉
感哥9 小时前
C++ STL 常用算法
c++
CoovallyAIHub9 小时前
英伟达ViPE重磅发布!解决3D感知难题,SLAM+深度学习完美融合(附带数据集下载地址)
深度学习·算法·计算机视觉
saltymilk19 小时前
C++ 模板参数推导问题小记(模板类的模板构造函数)
c++·模板元编程