STL容器(Stack, Queue, List, Vector, Deque, Priority_Queue, Map, Pair, Set, Multiset, Multimap)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 一、Stack(栈) 这个没啥好说的,就是后进先出的一个容器。 基本操作有: 1 stackq; 2 q.push(1); //入栈 3 q.pop(); //出栈 4 q.

一、Stack(栈)

  • 这个没啥好说的,就是后进先出的一个容器。
  • 基本操作有:
1     stack<int>q;
2     q.push(1);   //入栈
3     q.pop();     //出栈
4     q.top();     //返回栈顶成员
5     q.size();    //返回栈成员个数
6     q.empty();   //判断是否为空栈

二、Queue(队列)

  • 同上,先进先出的容器
  • 基本操作有:
1     queue<int>q;
2     q.push(1);    //入队列
3     q.pop();      //出队列
4     q.front();    //返回最上面(最后进入)的成员
5     q.size();     //返回队列成员个数
6     q.empty();    //判断是否为空队列

三、Priority_Queue(优先队列)

  • priority_queue的模板生命是带有三个参数的:priority_queue<type,container,function>
  • 和队列差不多,不过每个成员都有一个优先级参数,队列按照优先级进行排序
  • 默认container是vector,默认function比较模式为operator <(即栈顶为最大值)。
  • 基本操作有:
1     priority_queue<int,vector<int>,greater<int> >q;
2     q.push(1);    //入优先队列
3     q.top();      //返回优先队列头成员
4     q.pop();      //出优先队列
5     q.size();     //返回优先队列成员个数
6     q.empty();    //判断是否为空优先队列
  • 内置的排序方式有greater<>,和less<>,不填此参数默认为greater<>。当然也可以自己构造优先级函数
  • 例如对结构体重载运算符:
1     struct node{
2         int x,y;
3         
4         //重载运算符,按x的值排优先级
5         friend operator < (node a,node b){
6             return a.x < b.x;
7         }
8     };
  • 也可以将重载操作写在外面,优先队列中调用cmp函数
 1     struct node{
 2         int x,y;
 3     };
 4     struct cmp{
 5         //重载运算符,按x的值排优先级
 6         bool operator() (node a,node b){
 7             return a.x < b.x;
 8         }
 9     };
10 
11     priority_queue<node,vector<node>,cmp >q;

 

四、Deque(双向队列)

  • 一听就知道和Queue差不多 ,特殊的是Deque可是扩充内存。我们知道连续内存的容器不能随意扩充,所以Deque也不是真正意义上的扩充内存。
  • Deque是由一段一段构成的,当走到尾端时自动跳到下一段,(支持迭代器++操作)。每次扩充,申请一个段,实现了内存连续的假象。
  • 基本操作有:
 1     int num[] = {1,2,3,4,5,6};
 2     deque<int>q;        //创建一个空双向队列
 3     deque<int>p(5);     //创建一个具有5个成员的双向队列
 4     deque<int>s(5,1);   //创建一个具有5个成员且初始值为1的双向队列
 5     deque<int>s2(s);    //创建一个双向队列s2,并拷贝s中所有成员
 6     deque<int>n(num,num+5); //创建一个双向队列n,并拷贝num至num+5中元素入队
 7     
 8     q.push_front(a);     //头部入队
 9     q.pop_back(b);     //尾部入队
10     q.insert(iter,x);   //在iter位置插入x,iter为迭代器
11     q.pop_front();       //头部出队
12     q.pop_back();      //尾部出队
13     
14     q.front();          //返回头成员
15     q.back();           //返回尾元素
16     q.size();           //返回双向队列成员个数
17     q.max_size();       //返回系统支持成员最大个数
18     q.empty();          //判断双向队列是否为空
19     
20     q.at(i);            //返回第i个元素
21     q.begin();          //返回头部迭代器
22     q.end();            //返回尾部迭代器
23     q.rbegin();         //返回尾部反向迭代器
24     q.rend();           //返回头部反向迭代器
25     
26     q.erase(iter);      //删除iter元素,iter为迭代器
27     q.clear();          //情况双向队列
28     q.swap(p);          //交换q和p中的所有元素

 

  •  Deque采用分块线型结构存储数据,两个迭代器分别指向首尾元素,而且拥有具有高效的push_back(),push_front()函数。
  •  正因如此,所以Deque不易实现capacity和reverse函数。
  • Deque的缺点:频繁的插入删除时候,Deque并不适合。

五、Vector(动态数组)

  • 顾名思义,不定长数组。
  • uhmmm没啥好说的
  • 基本操作有:
 1     vector<int>q;           //创建空Vector
 2     vector<int>p(5);        //创建拥有5个成员的Vector
 3     vector<int>s(5,1);      //创建拥有5个成员,且初始值为1的Vector
 4     vector<int>s2(s);       //创建s2,并拷贝s元素给s2
 5     vector<int>s3(s.begin(),s.end());   //创建s3,拷贝s.begin()至s.end()中元素给s3
 6     
 7     q.push_back(x);          //尾部加入元素
 8     q.insert(iter,x);        //在iter位置插入x,传回新数据位置
 9     q.insert(iter,n,x);      //在iter位置插入n个x,无返回值
10     q.insert(iter,l,r);      //在iter位置插入[l,r)区间内的数据,无返回值
11     q.pop_back();            //删除最后一个元素
12     q.front();               //返回第一个数据
13     q.back();                //返回最后一个数据
14 
15     q.size();                //返回容器内成员个数
16     q.resize(x);              //重新指定容器大小
17     q.empty();               //判断Vector是否为空
18     q.capacity();            //返回Vector可用空间的大小
19     q.reserve();             //重新指定空间大小,小于当前capacity时保持为原本的capacity值
20     q.swap(p);               //交换p,q容器内元素
21     q.assign(iter1,iter2);   //将区间[iter1,iter2)内元素赋值给vector,并清空vector容器之前的内容。
22     q.assign(n,x);           //将n个x赋值到vector中,并清空vector容器之前的内容。
23     
24     q.at(i);                 //返回第i个元素
25     q.begin();               //返回头位置迭代器
26     q.end();                 //返回尾位置迭代器
27     q.rbegin();              //返回尾部反向迭代器
28     q.rend();                //返回头部反向迭代器
29 
30     q.clear();               //情况Vector
31     q.erase();               //删除iter位置元素
32     q.erase(iter1,iter2);    //删除[iter1,iter2)区间内的元素
  • 此外,vector还可以用数组的方式引用,因为以及内置重载了[],例如q[0]等同于q.at(1)。

六、List(链表)

  • 链表其实用的不多
  • 自己也没怎么用过 =7= 直接放代码操作了
  • 基本操作:
 1     list<int>q;           //创建空List
 2     list<int>p(5);        //创建拥有5个成员的List
 3     list<int>s(5,1);      //创建拥有5个成员,且初始值为1的List
 4     list<int>s2(s);       //创建s2,并拷贝s元素给s2
 5     list<int>s3(s.begin(),s.end());   //创建s3,拷贝s.begin()至s.end()中元素给s3
 6 
 7     q.back()                 //返回最后一个元素 
 8     q.begin()                //返回指向第一个元素的迭代器 
 9     q.clear()                //删除所有元素 
10     q.empty()                //如果list是空的则返回true 
11     q.end()                  //返回末尾的迭代器 
12     q.erase()                //删除一个元素 
13     
14     q.front()                //返回第一个元素 
15     q.get_allocator()        //返回list的配置器 
16     q.insert()               //插入一个元素到list中 
17     q.max_size()             //返回list能容纳的最大元素数量 
18     q.merge()                //合并两个list 
19     q.pop_back()             //删除最后一个元素 
20     q.pop_front()            //删除第一个元素 
21     q.push_front()           //在list的头部添加一个元素 
22     
23     q.rbegin()               //返回指向第一个元素的逆向迭代器 
24     q.remove()               //从list删除元素 
25     q.remove_if()            //按指定条件删除元素 
26     q.rend()                 //指向list末尾的逆向迭代器 
27     q.resize()               //改变list的大小 
28     q.reverse()              //把list的元素倒转 
29     q.size()                 //返回list中的元素个数 
30     q.sort()                 //给list排序 
31     q.splice()               //合并两个list 
32     q.swap()                 //交换两个list 
33     q.unique()               //删除list中重复的元素

七、Pair(对)

  • 就是合成两个数据,这个用结构体模拟也行,但是直接使用Pair会方便很多
  • 基本操作如下:
1     pair<int,int>q;     //创建一个空对
2     pair<int,int>p(2,3);//创建一个对p,并分别赋值2,3
3     pair<int,int>s(p);  //创建一个对s,拷贝p给s
4     
5     //赋值利用make_pair函数
6     q = make_pair(1,2);
7     //访问pair内元素操作
8     q.first;        //返回成员第一个数据
9     q.second;       //返回成员第二个数据

八、Set(集合)

  • 首先Set遵循数学集合三特性,无重复、无序性、确定性。我就不解释了。
  • Set中内置红黑树进行排序,所以插入删除效率很高。
  • 常用操作如下:
 1     int a[] = {1,2,3,4,5};
 2     set<int>q;
 3     set<int>p;
 4     
 5     q.insert(x);      //集合中插入元素
 6     q.insert(a,a+5);  //插入数组a至a+5的元素
 7     q.find(x);        //返回x值位置的迭代器,找不到返回q.end()  
 8     q.erase(iter);    //删除集合中的元素
 9     q.size();         //返回当前set容器中的元素个数
10     q.count();        //返回某个值元素的个数(根据set的特性,就是判断这个元素在不在,返回0或1)
11     q.begin();        //返回头位置迭代器
12     q.end();          //返回尾位置迭代器
13     q.rbegin();       //返回尾部反向迭代器
14     q.rend();         //返回头部反向迭代器
15     q.clear();        //删除set容器中的所有的元素
16     q.empty();        //判断set容器是否为空
17     q.lower_bound();  //返回指向大于(或等于)某值的第一个元素的迭代器
18     q.upper_bound();  //返回大于某个值元素的迭代器
  • 当然,你也可以自定义Set内部的排序操作,例如:
1     struct cmp{
2         bool operator() (const node &a,const node &b){
3             return a.x < b.x;
4         }
5     };
6     
7     set<node,cmp>q;

九、Map

  • 不知道该翻译成啥,干脆不翻译了 =7=
  • map是一种关联容器,例如map<int,int>,第一个元素可以称为关键字,类似数组的下标,不会重复出现,而第二个元素为关键字的值,类似数组中存的元素,可以重复。
  • map不能直接修改关键字,只能通过修改关键字的值间接修改关键字。
  • 和Set一样,map也是内置红黑树对关键字进行排序。能够实现快速查找和删除功能。
  • 基本操作:
 1     map<int,int>q;
 2     
 3     q.insert(pair<int,int>(1,2));       //通过pair进行插入操作
 4     q.insert(map<int,int>::value_type (1,2));//通过value_type进行插入
 5     q[1] = 2;           //用数组方式进行插入
 6     /*三者不同的是,当map存在这个关键字时
 7      *数组方式会覆盖关键字的值,而insert操作无法插入。
 8     */
 9     
10     q.size();       //返回容器内元素个数
11     q.empty();      //判断容器是否为空 
12     q.begin();      //返回头位置迭代器
13     q.end();        //返回尾位置迭代器
14     q.rbegin();     //返回尾部反向迭代器
15     q.rend();       //返回头部反向迭代器
16     q.find(key);    //查找并返回关键字key的位置
17     q.count(key);   //查询是否有关键字key(有则返回1,否则0)
18     q.lower_bound();//返回键值>=给定元素的第一个位置
19     q.upper_bound();//返回键值>给定元素的第一个位置
20     q.erase(iter);  //删除迭代器iter的元素
21     q.erase(iter1,iter2);//删除[iter1,iter2)区间内的元素
22     q.erase(key);   //删除关键字为key的元素
23     q.clear();      //清空容器
24     q.swap(p);      //交换两个map
25     q.key_comp();   //返回比较元素key的函数
26     q.max_size();   //返回可以容纳的最大元素个数
27     q.value_comp(); //返回比较元素value的函数
28     q.equal_range();//返回特殊条目的迭代器对
  • 当然你可以自己写内部排序函数
  • 例如结构体中重载<号,或者编写仿函数,例如:
1 class sort{
2 
3 public:
4     bool operator() (node const &a,node const &b) const{
5         return a.x < b.x;
6     }
7 
8 };

十、Multiset(多重集合)

  • 和Set不同的地方是Multiset允许一个值出现多次;
  • 操作和set相同。但是因为值能重复出现,所有某些函数的返回值将会改变,例如:
  • multiset::count(key)返回值可能大于1;(多个关键值存在)
  • multiset::erase(key)会将对应的key全部删掉。
  • 对于set总是有set::equal_range(key)的返回值总有++iter1 = iter2.但multiset不一定(元素相同)

十一、Multimap

  • 同上,和map类似,可以存在相同的关键字。

 

本来想讲BitSet,但是觉得bitset比较特殊,到时候专门详细讲吧。

 

其实所有容器都挺简单的,根据特性基本都能想出操作。熟悉了这些容器之后,对做题和学习很有帮助的。

记住操作没啥用,得不断的练习使用这些容器 ,才能熟练操作。

 

emmmm都说的很简陋,本来想讲每个容器的具体实现一起构造方式。后来一想,篇幅太长了,还容易误导别人觉得容器很复杂。这些都算是学个表面吧,最重要的还是不断敲敲敲,熟悉各种用法。

 

大致就这样吧 =7=


 后续:Stack,Queue,Pair并不是C++的标准容器,但是我觉得性质差不多,就一起讲了,但是防止误导初学者,这里还是提一下。

目录
相关文章
|
2月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
55 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
2月前
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
28 3
|
2月前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
55 5
|
2月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
59 2
|
2月前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(三)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
2月前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(二)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
2月前
|
存储 编译器 C++
【C++】C++ STL 探索:List使用与背后底层逻辑(一)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
4月前
|
存储 Java 索引
|
2天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
118 77
|
4天前
|
数据建模 应用服务中间件 nginx
docker替换宿主与容器的映射端口和文件路径
通过正确配置 Docker 的端口和文件路径映射,可以有效地管理容器化应用程序,确保其高效运行和数据持久性。在生产环境中,动态替换映射配置有助于灵活应对各种需求变化。以上方法和步骤提供了一种可靠且易于操作的方案,帮助您轻松管理 Docker 容器的端口和路径映射。
29 3