当前位置: 首页 > news >正文

【STL】set

C C C++ S T L STL STL 标准库中, s e t set set 是一个关联式容器,表示一个集合,用于存储唯一元素的容器。 s e t set set 中的元素会自动按照一定的顺序排序(默认情况下是升序)。这意味着在 s e t set set 中不能插入重复的元素,因为重复的元素会被忽略。

文章目录

  • 前言 —— 关联式容器
  • 一、set 的介绍
  • 二、set 的使用(常用接口)
    • 1. 常见构造
    • 2. iterator 的使用
    • 3. 增删查
    • 4. multiset 和 set 的差异
  • 三、set 的模拟实现
  • 总结


前言 —— 关联式容器

关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构,两个位置有紧密的关联关系,交换一下,他的存储结构就被破坏了。

关联式容器中的元素是按关键字 k e y key key)来保存和访问的。

C C C++ S T L STL STL 中主要提供了以下关联式容器

  1. s e t / m u l t i s e t set/multiset set/multiset集合 / / /多重集合

  2. m a p / m u l t i m a p map/multimap map/multimap映射 / / /多重映射

  3. u n o r d e r e d _ s e t / u n o r d e r e d _ m u l t i s e t unordered\_set/unordered\_multiset unordered_set/unordered_multiset无序集合 / / /多重无序集合

  4. u n o r d e r e d _ m a p / u n o r d e r e d _ m u l t i m a p unordered\_map/unordered\_multimap unordered_map/unordered_multimap无序映射 / / /多重无序映射

S T L STL STL 标准库中的 m a p map map s e t set set 底层是用红黑树实现的,红黑树是一颗平衡二叉搜索树

s e t set set k e y key key 搜索场景的结构, m a p map map k e y / v a l u e key/value key/value 搜索场景的结构。


一、set 的介绍

s e t set set 系列根据容器是否支持插入相同元素而分为了 s e t set set(集合)和 m u l t i s e t multiset multiset(多重集合)。

s e t set set 其实就是按特定顺序存储唯一元素的容器

在这里插入图片描述

m u l t i s e t multiset multiset 其实就是按特定顺序存储元素的容器,其中多个元素可以具有等效的值

在这里插入图片描述

由于最常用的还是 s e t set set 容器,因此这里主要介绍的是 s e t set set,而 m u l t i s e t multiset multiset s e t set set 只有在一些地方有略微的不同,稍注意一下即可。

s e t set set 的声明如下:

template < class T, 					// set::key_type/value_typeclass Compare = less<T>, 	// set::key_compare/value_compareclass Alloc = allocator<T> 	// set::allocator_type> class set;
  1. T T T 就是 s e t set set 底层关键字的类型。

  2. s e t set set 默认要求 T T T 支持小于比较less<T>升序排序),如果不支持或者想按自己的需求走可以自行实现仿函数传给第二个模板参数。

  3. s e t set set 底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第三个模板参数。

注意:一般情况下,我们都不需要传后两个模版参数。

s e t set set 底层是用红黑树实现的,增删查效率是 O ( l o g N ) O(logN) O(logN)迭代器遍历是走的搜索树的中序,所以是有序的。


二、set 的使用(常用接口)

下面只列举了 s e t set set 最常用的几个接口,更多详细信息可以自行查官方文档: s e t set set

1. 常见构造

构造 ( c o n s t r u c t o r ) (constructor) (constructor) 函数声明接口说明
s e t ( ) set() set()无参默认构造
s e t ( c o n s t s e t & x ) set(const\ set\&\ x) set(const set& x)拷贝构造
s e t ( I n p u t I t e r a t o r f i r s t , I n p u t I t e r a t o r l a s t ) set(InputIterator\ first, InputIterator\ last) set(InputIterator first,InputIterator last)使用迭代器区间构造
s e t ( i n i t i a l i z e r _ l i s t < v a l u e _ t y p e > i l ) set (initializer\_list<value\_type> il) set(initializer_list<value_type>il)使用 i n i t i a l i z e r initializer initializer 列表构造
  1. 无参默认构造:
set<int> s1;					// 升序
set<int, greater<int>> s2;		// 降序
  1. 拷贝构造:
set<int> s = { 3,1,2,4,5 };
set<int> s1(s);					// 升序
set<int, greater<int>> s2 = s;	// 降序
  1. 迭代器区间构造:
int a[] = { 3,1,2,4,5 };
vector<int> v = { 3,1,2,4,5 };
set<int> s1(a ,a + 5);							// 升序
set<int, greater<int>> s2(v.begin() ,v.end());	// 降序
  1. i n i t i a l i z e r initializer initializer 列表构造:
set<int> s1 = { 3,1,2,4,5 };				// 升序
set<int, greater<int>> s2({ 3,1,2,4,5 });	// 降序

2. iterator 的使用

i t e r a t o r iterator iterator 的使用接口说明
b e g i n ( ) begin() begin() + + + e n d ( ) end() end()正向迭代器( i t e r a t o r iterator iterator
r b e g i n ( ) rbegin() rbegin() + + + r e n d ( ) rend() rend()反向迭代器( r e v e r s e _ i t e r a t o r reverse\_iterator reverse_iterator
  1. s e t set set 的迭代器支持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是二叉搜索树迭代器遍历走的是中序遍历

  2. 支持迭代器就意味着支持范围 f o r for for

  3. s e t set set i t e r a t o r iterator iterator c o n s t _ i t e r a t o r const\_iterator const_iterator不支持迭代器修改数据,修改关键字数据,就破坏了底层搜索树的结构。

  4. s e t set set 的迭代器是一个双向迭代器iterator -> a bidirectional iterator to const value_type
    在这里插入图片描述

set<int> s = { 3,5,4,2,1 };// 1.正向迭代器
auto it = s.begin();
while (it != s.end())
{cout << *it << " ";++it;
}
cout << endl;// 2.反向迭代器
auto rit = s.rbegin();
while (rit != s.rend())
{cout << *rit << " ";++rit;
}
cout << endl;// 3.范围for
for (auto& e : s)
{cout << e << " ";
}
cout << endl;

输出:

1 2 3 4 5
5 4 3 2 1
1 2 3 4 5

3. 增删查

s e t set set 增删查接口说明
i n s e r t insert insert插入 v a l val val 数据
e r a s e erase erase删除 v a l val val 数据
f i n d find find查找 v a l val val,返回 v a l val val 位置的迭代器(没找到返回 e n d ( ) end() end()
c o u n t count count查找 v a l val val,返回 v a l val val 的个数
l o w e r _ b o u n d lower\_bound lower_bound返回大于等于 v a l val val 位置的迭代器
u p p e r _ b o u n d upper\_bound upper_bound返回大于 v a l val val 位置的迭代器
  1. 插入数据(insert):
vector<int> v = { 1,2,5 };
set<int> s;// 1.直接插入
s.insert(3);
// 2.指定位置插入
s.insert(s.begin(), 4);
// 3.迭代器区间插入
s.insert(v.begin(), v.end());
// 4.initializer插入
s.insert({ 6,7,8 });for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 7 8
  1. 查找 + 删除数据(find + erase):
set<int> s = { 1,2,3,4,5,6,7,8 };// 1.指定位置删除
s.erase(s.begin());
// 2.指定数据删除
s.erase(5);
// 3.迭代器区间删除
auto it = s.find(4);		// 返回值对应的迭代器(没找到就返回s.end())
if(it != s.end())s.erase(s.begin(),it);	// 前闭后开[s.begin(),it)for (const auto& e : s) cout << e << " "; cout << endl;

输出:

4 6 7 8
  1. lower_bound / upper_bound
set<int> s = { 1,2,3,4,5,6,7,8 };auto it1 = s.lower_bound(3);	// 返回第一个值 >= 3的迭代器
auto it2 = s.upper_bound(7);	// 返回第一个值 > 3的迭代器// 删除[3,7]区间的数据
s.erase(it1,it2);for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 8

4. multiset 和 set 的差异

m u l t i s e t multiset multiset s e t set set 的使用基本完全类似,主要区别点在于 m u l t i s e t multiset multiset 支持值冗余

那么 i n s e r t / f i n d / c o u n t / e r a s e insert/find/count/erase insert/find/count/erase 都围绕着支持值冗余有所差异:

  1. i n s e r t insert insert 可以插入相同的值
multiset<int> s = { 1,2,3,4,5,6,7,8 };
s.insert(6);
s.insert(6);
s.insert(6);for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 6 6 6 7 8
  1. 如果要查找的 x x x 有多个值, f i n d find find 会返回中序的第一个
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };auto it = s.find(6);
while (it != s.end() && *it == 6)
{cout << *it << " ";++it;
}
cout << endl;

输出:

6 6 6 6
  1. c o u n t count count 会返回 x x x 的实际个数:
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };cout << "6的个数:" << s.count(6) << endl;
cout << "9的个数:" << s.count(9) << endl;

输出:

6的个数:4
9的个数:0
  1. e r a s e erase erase 指定值删除时,会删除所有的 x x x
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };// 1.指定迭代器删除只会删除一个值
auto it = s.find(6);
s.erase(it);
for (const auto& e : s) cout << e << " "; cout << endl;// 2.指定值删除会删除所有的值
s.erase(6);
for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 6 6 7 8
1 2 3 4 5 7 8

三、set 的模拟实现


总结


http://www.mrgr.cn/news/98346.html

相关文章:

  • 【LLM】解锁Agent协作:深入了解谷歌 A2A 协议与 Python 实现
  • 前端工程化之自动化构建
  • 07软件测试需求分析案例-修改用户信息
  • UNITY 屏幕UI自适应
  • 使用SVM对心脏数据是否患病进行分类预测
  • UNet深度学习实战遥感航拍图像语义分割
  • 科研软件分享
  • deepin使用autokey添加微信快捷键一键显隐ctrl+alt+w
  • Linux内核中struct net_protocol的early_demux字段解析
  • HarmonyOS 第2章 Ability的开发,鸿蒙HarmonyOS 应用开发入门
  • 7.thinkphp的路由
  • 观察者模式(行为模式)
  • Activiti(六)- 启动、挂起、激活,查询及删除流程实例
  • 关于 驱动开发方法 的详细分类、核心特点及对比分析,涵盖 TDD、MDD、BDD、DDD、ATDD、FDD、PDD 等主流方法
  • EMMOE:开放环境中具身移动操控的综合基准
  • C 语言中经典的数据结构
  • 【数据结构_5】链表(模拟实现以及leetcode上链表相关的题目)
  • 一种基于学习的多尺度方法及其在非弹性碰撞问题中的应用·
  • 【深度学习】PyTorch实现VGG16模型及网络层数学原理
  • Python 数组里找出子超集