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

set(关联性容器)

众所周知,不会set的人就不会c++(你自己编的吧!),到底什么是set呢?我们今天就来了解一下set的奥秘.

set是啥

set 作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set 中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set 中数元素的值不能直接被改变。与map 的使用方法大致都相同。这时你们就可能有疑问了,啥是map呢?我们抽时间会给大家讲的(反正不是下期)

set的定义 

set<类型> 对象名; 如:set<int> s;

添加元素

set<int> s;
s.insert(8);
s.insert(10);
s.insert(6);
s.insert(8); //重复元素不会插入

set遍历

set 的遍历也是使用迭代器进行遍历, 可以正序遍历也可以反序遍历。

正序遍历

set<int>s;
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++)
    cout<<*it<<endl;

反序遍历

set<int>::reverse_iterator it;
for(it=s.rbegin();it!=s.rend();it++)
    cout<<*it<<endl

容器与迭代器

vector ​​​,stack ​​,queue ​​,map ​​​,set ​​​ 都是STL提供的标准数据结构,他们共同的特点是都是容器,用来存储元素集合。为了统一他们的使用方法,STL提供了迭代器。

容器

容器迭代器功能解释
vector随机访问
deque随机访问双端队列,可以从前后 push,pop 元素
list双向链表
set/multiset双向multiset 是允许有重复元素的 set ,元素保持有序
map/multimap双向multimap 是允许有重复元素的map ,元素是pair 保持有序
stack不支持迭代器
queue不支持迭代器队列
priority_queue不支持迭代器优先队列,每次可以从栈顶取出当前最小
容器添加元素的效率删除元素的效率查找元素访问中间的元素
vector加在尾部 𝑂(1),加在中间 𝑂(𝑛)。𝑂(𝑛)𝑂(𝑛)𝑂(1)
list𝑂(1)𝑂(1)𝑂(𝑛)𝑂(𝑛)
stack只能加在栈顶 𝑂(1)只能删除栈顶 𝑂(1)无法查找无法访问
queue只能加在队尾 𝑂(1)只能删除队首 𝑂(1)无法查找无法访问
set/map𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑛)更高效率的访问需要自己实现

迭代器

迭代器按照定义方式分成以下四种:

1.正向迭代器(最常用),定义方法如下:
容器类名::iterator 迭代器名;
map<int, double>::iterator itor;
2.常量正向迭代器,定义方法如下:
容器类名::const_iterator 迭代器名;
vector<bool>::const_iterator citor;
3.反向迭代器,定义方法如下:
容器类名::reverse_iterator 迭代器名;
set<bool>::reverse_iterator ritor;
4.常量反向迭代器,定义方法如下:
容器类名::const_reverse_iterator 迭代器名;
set<int>::const_reverse_iterator critor;
容器方法解释
begin()返回容器首个元素的地址
end() ​返回容器最后一个元素再下一个元素的地址
rbegin()返回容器最后一个元素的地址
rend()返回容器首个元素再前一个元素的地址
find(value) ​查找元素,如果找到返回迭代器位置,否则返回end() 的位置
erase(iterator)删除迭代器元素

为了更深入理解迭代器的使用,我们试着运行一下下面的程序:

#include <bits/stdc++.h>
using namespace std;
set<int> st;
set<int>::iterator itor;
int main(){ 
    for(int i=1;i<6;i++){
        st.insert(i);
        itor=st.find(3);
        cout<<i<<" find(3) = end() : ";
        if(itor==st.end())
            cout<<"Yes";
        else
            cout<<"No";
        cout<<" end 位置读取值"<<*st.end()<<endl;
    }
    return 0;
}
1 find(3) = end() : Yes end 位置读取值1
2 find(3) = end() : Yes end 位置读取值2
3 find(3) = end() : No end 位置读取值3
4 find(3) = end() : No end 位置读取值4
5 find(3) = end() : No end 位置读取值5

上面是程序运行的结果,当我们插入了元素3后,发现 𝑓𝑖𝑛𝑑(3)!=𝑠𝑡.𝑒𝑛𝑑(),因此我们知道 end() 给出的地址并不是最后一个元素的地址。

同时发现,虽然 end 对应的是容器最后一个元素再下一个元素的地址,但我们用 ∗st.end() ​ 去读取值的时候,返回的却是最后一个元素的值。

迭代器本身支持 ++​ 和 −−操作,但不能够写成 𝑖𝑡𝑜𝑟=𝑖𝑡𝑜𝑟+1 ​。 ++操作返回的是下一个地址,−− ​ 是上一个。

但迭代器不一定支持 +=操作,只有可以随机访问的迭代器(例如:vector ​ 的迭代器),支持此类操作。

常用操作

begin(),               //返回set容器的第一个元素
end(),                 //返回set容器的最后一个元素
clear(),               //删除set容器中的所有的元素
empty(),               //判断set容器是否为空
max_size(),            //返回set容器可能包含的元素最大个数
size(),                //返回当前set容器中的元素个数
rbegin(),              //返回的值和end()相同
rend(),                //返回的值和begin()相同
erase(iterator),       //删除定位器iterator指向的值
erase(first,second),   //删除定位器first和second之间的值
erase(key_value),      //删除键值key_value的值
find() ,              //返回给定值值得定位器,如果没找到则返回end()。
  
set中还有两个非常重要的函数,lower_bound()和upper_bound()。这两个函数都需要传入一个值。
lower_bound返回的是大于或等于被查询元素的第一个元素位置的迭代器,如果找不到,迭代器则为set.end() 
upper_bound返回值则是>给定val的最小指针(iterator)。
rbegin() 和 rend()为反向迭代器。

因为set ​​ 中的元素本身是有序的,因此 begin() ​​ 会直接返回集合中最小的元素的位置,而 end()−− ​ 返回的是集合中最大元素的位置。

既然set 本身支持模板(泛型编程),那么set 也可以用来保存我们自定义的一些数据类型。那么这些类型将会按照什么样的顺序来排列呢?

同排序函数相同,我们可以自行定义比较的方法,但具体使用同sort 略有不同,需要自己定义一个struct 来做具体类型的比较,同时要定义一个名为operator 的bool 类型函数,具体请看下面的代码。

#include <bits/stdc++.h>
using namespace std;
//自定义比较结构体
struct Cmp{
    bool operator()(int l,int r){ 
        return l%10>r%10;
    }
};
int main(){
    set<int,Cmp>s;
    for(int i=7;i<27;i++)
        s.insert(i);
    set<int>::iterator it;
    for(it=s.begin();it!=s.end();it++)
        cout<<*it<<endl;
    return 0;
}

 9 8 7 16 15 14 13 12 11 10

以上为程序运行结果,我们来解释一下为什么会出现这样的运行结果呢?

首先,我们自定义的比较类型中会将一个数模 10的结果进行比较,并将更大的排在前面。另外因为set 会去重,所以在插入17 时,会发现已经存在%10=7 的数了,因此插入数据失败。

尾声

今天咱们就讲到这里,下篇博文再见👋👋

相关文章:

  • 网站构架怎么做/百度关键词优化大师
  • 哪些网做网站比较好/济南seo网站优化
  • 网站建设和优化那本书好/什么是sem
  • 宁波外贸网站制作/一份完整的营销策划书
  • 武汉网站设计制作公司哪家好/推广商
  • 怎么才能登网站做外贸/网站运营推广选择乐云seo
  • python中的% 是什么意思, 起到什么作用?
  • vue+antd搭建后台管理界面模版(PC端),适配中文、英文、日文 mock数据,开箱即用
  • php项目管理系统 。集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体,是一款专业的研发项目管理软件
  • java 三级缓存
  • 记一次简单的白加黑测试
  • 【关于时间序列的ML】项目 7 :使用机器学习进行每日出生预测
  • 马斯克辞任CEO,产品经理如何用项目协作软件武装自己?
  • 106. 从中序与后序遍历序列构造二叉树
  • 让人恶心的多线程代码,性能怎么优化
  • 「PAT乙级真题解析」Basic Level 1096 大美数 (问题分析+完整步骤+伪代码描述+提交通过代码)
  • 使用Anaconda安装TensorFlow详细教程
  • wifi热点setting