跳到主要内容C++ STL 常用容器用法总结 | 极客日志C++算法
C++ STL 常用容器用法总结
本文总结了 C++ STL 中常用容器的用法,包括 map、unordered_map、stack、vector、queue、deque、priority_queue 和 set。详细说明了各容器的定义、核心函数及代码示例。Map 基于红黑树有序存储,Unordered_map 基于哈希表无序且查找快。Stack 和 Queue 分别为先进后出和先进先出结构。Vector 为动态数组,Deque 支持两端操作。Priority_queue 自动排序。Set 去重有序。文中还涉及 rand/srand 随机数生成基础。
GitMaster0 浏览 C++ STL 常用容器用法总结
1. map 用法
定义
map 是 STL 的一个关联容器,它提供一对一的映射。第一个可以称为关键字 (key),每个关键字只能在 map 中出现一次;第二个称为该关键字的值 (value)。map 是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。
map 可以自动建立 Key-value 的对应,key 和 value 可以是任意类型。根据 key 值快速查找记录,查找的复杂度基本是 log(n)。快速插入 Key-Value 记录。快速删除记录,根据 Key 修改 value 记录,遍历所有记录。
map 内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而 AVL 是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此 map 内部的所有元素都是有序的,红黑树的每一个节点都代表着 map 的一个元素。
函数方法
| 函数 | 说明 |
|---|
| begin()/end() | 返回指向 map 头部/尾部的迭代器 |
| clear() | 清空所有元素 |
| count() | 查看元素是否存在,因为 map 中键是唯一的,所以存在返回 1,不存在返回 0 |
| empty() | 如果 map 为空则返回 true,否则返回 false |
| erase(it) | 删除迭代器对应的键和值 |
| erase(key) | 根据映射的键删除键和值 |
| erase(first,last) | 删除左闭右开区间迭代器对应的键和值 |
| find() | 返回键为 key 的映射的迭代器,数据不存在时,返回 mp.end() |
| insert() | 插入元素 |
| size() | 返回 map 中元素的个数 |
| lower_bound() | 返回一个迭代器,指向键值>= key 的第一个元素 |
| upper_bound() | 返回一个迭代器,指向键值> key 的第一个元素 |
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
map<int,string>mp1;
mp1.insert(pair<int, string>(000, "student_zero"));
mp1.insert(map<int, string>::value_type(001, "student_one"));
mp1[123] = "student_first";
mp1.insert({4,"stu"});
auto iter = mp1.find(123);
if(iter!=mp1.end()) cout<<"Find, the value is"<<iter->second<<endl;
else cout<<"Do not Find"<<endl;
iter = mp1.find(123);
mp1.erase(iter);
int n = mp1.erase(123);
mp1.erase(mp1.begin(), mp1.end());
int Size = mp1.size();
map<int,string>mp2={ {2, "two"}, {4, "four"}, {5, "five"} };
auto it = mp2.lower_bound(3);
if (it != mp2.end()) {
cout << "Key: " << it->first << ", Value: " << it->second << endl;
} else {
cout << "No element found." << endl;
}
return 0;
}
2. unordered_map 用法
定义
unordered_map 内部实现了一个哈希表 (也叫散列表,通过把关键码值映射到 Hash 表中一个位置来访问记录,查找的时间复杂度可达到 O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序都是无序的。
函数方法
| 函数 | 说明 |
|---|
| begin()/end() | 返回指向头部/尾部的迭代器 |
| clear() | 清空所有元素 |
| count() | 查看元素是否存在,因为 map 中键是唯一的,所以存在返回 1,不存在返回 0 |
| empty() | 如果 map 为空则返回 true,否则返回 false |
| erase(it) | 删除迭代器对应的键和值 |
| erase(key) | 根据映射的键删除键和值 |
| erase(first,last) | 删除左闭右开区间迭代器对应的键和值 |
| find() | 返回键为 key 的映射的迭代器,数据不存在时,返回 end() |
| insert() | 插入元素 |
| size() | 返回 unordered_map 中元素的个数 |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
unordered_map<int,string>mymap{{5,"张大"},{6,"李四"}};
mymap[2]="张三";
mymap.insert(pair<int ,string>(3,"陈二"));
auto iter=mymap.begin();
while(iter!=mymap.end()){
cout<<iter->first<<','<<iter->second<<endl;
++iter;
}
auto iterator = mymap.find(2);
if (iterator != mymap.end()) cout << endl<< iterator->first << "," << iterator->second << endl;
unordered_map<key,t>::iterator it;
(*it).first;
(*it).second;
(*it)
return 0;
}
3. stack 用法
定义
函数方法
| 函数 | 说明 |
|---|
| push() | 元素入栈 |
| pop() | 移除栈顶元素 |
| top() | 获取栈顶元素 |
| empty() | 检查栈内是否为空 |
| size() | 返回栈内元素的个数 |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
stack<int>s;
for(int i=0;i<5;i++){
s.push(i);
}
while(!s.empty()){
int t=s.top();
cout<<t<<" ";
s.pop();
}
return 0;
}
4. vector 用法
定义
vector 是 STL 中的一种常用的容器,长度可变(size),类似数组,可以代替长度未知的数组。
函数方法
| 函数 | 说明 |
|---|
| begin()/end() | 返回指向头部/尾部的迭代器 |
| clear() | 清空所有元素 |
| empty() | 如果 vector 为空则返回 true,否则返回 false |
| erase(it) | 删除向量中迭代器指向元素 |
| push_back() | 向量尾部增加一个元素 |
| pop_back() | 删除向量中最后一个元素 |
| insert(it,x) | 插入元素 |
| size() | 返回 vector 中元素的个数 |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
vector<int>a;
a.push_back(200);
a.push_back(20);
a.push_back(300);
a.push_back(50);
a.push_back(60);
a.push_back(100);
vector<int>::iterator it;
for(it=a.begin();it!=a.end();it++){
if (*it==300){
a.erase(it);
}
}
for(it=a.begin();it!=a.end();it++){
cout<<*it<<endl;
}
printf("\n");
auto it_begin=a.begin()+1;
vector<int>::const_iterator it_end=a.end()-1;
a.erase(it_begin,it_end);
for(it=a.begin();it!=a.end();it++){
cout<<*it<<endl;
}
printf("\n");
vector<int>::iterator it_last=a.end()-1;
a.erase(it_last);
for(it=a.begin();it!=a.end();it++){
cout<<*it<< " ";
}
return 0;
}
5. queue 用法
定义
队列是先进先出的数据结构,可以在队尾添加元素,队首删除元素。
函数方法
| 函数 | 说明 |
|---|
| front()/back() | 返回队尾首/ 队尾元素 O(1) |
| push() | 队尾添加元素 O(1) |
| pop() | 删除队首元素 O(1) |
| empty() | 检查队列是否空 O(1) |
| size() | 返回队列的元素数量 O(1) |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
queue<int>q;
q.push(10);
q.push(15);
q.push(6);
q.push(9);
cout<<q.front()<<" "<<q.back()<<" "<<q.size()<<endl;
while(!q.empty()){
cout<<q.front()<<" ";
q.pop();
}
cout<<endl;
return 0;
}
6. deque 用法
定义
deque 是双端队列,允许在两端进行插入和删除操作的线性数据结构。适合用于频繁插入和删除元素的场景。
函数方法
| 函数 | 说明 |
|---|
| push_back(x)/push_front(x) | 把 x 插入队尾后 / 队首 O(1) |
| back()/front() | 返回队尾 / 队首元素 O(1) |
| pop_back() / pop_front() | 删除队尾 / 队首元素 O(1) |
| begin() | 返回指向第一个元素的迭代器 |
| end() | 返回指向末尾元素后一位置的迭代器 |
| find(q.begin(), q.end(), x) | 在队列中查找 x,并返回迭代器 |
| insert(iterator pos, const T& value) | 在 pos 位置插入 value 元素 |
| erase(iterator it) | 删除双端队列中的某一个元素(注意是迭代器不是具体的数值) |
| erase(iterator first,iterator last) | 删除双端队列中 [first,last) 中的元素 |
| empty() | 检查队列是否空 O(1) |
| size() | 返回队列的元素数量 O(1) |
| clear() | 清空队列 |
代码
#include<bits/stdc++.h>
using namespace std;
deque<int>q1,q2;
int main(){
for(int i=0;i<5;i++){
q1.push_front(i);
q2.push_back(i);
}
cout<<q1.front()<<" "<<q1.back()<<endl;
q1.pop_front();
q1.pop_back();
auto iter = find(q2.begin(), q2.end(), 1);
if (iter != q2.end()) cout << *iter << endl;
else cout << "没找到" << endl;
q2.erase(iter);
for(int i=0;i<q1.size();i++){
cout<<q1[i]<<" ";
}
cout<<endl;
for(int i=0;i<q2.size();i++){
cout<<q2[i]<<" ";
}
cout<<endl;
return 0;
}
7. priority_queue 用法
定义
优先队列是一种特殊的队列,它允许我们快速访问队列中具有最高(或最低)优先级的元素,内部会自动按照规则排列。默认情况下队列顶部元素是最大值,不能随机访问,只能从队首访问元素。
函数方法
| 函数 | 说明 |
|---|
| q.top() | 访问队首元素 |
| q.pop() | 移除队首元素 |
| q.push() | 向队列添加元素 |
| q.empty() | 检查队列是否空 O(1) |
| q.size() | 返回队列的元素数量 O(1) |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int>a;
priority_queue<int,vector<int>,less<int> >b;
priority_queue<int, vector<int>, greater<int> > c;
for(int i=0;i<5;i++){
a.push(i);
b.push(i);
c.push(i);
}
while(!a.empty()){
int t=a.top();
a.pop();
printf("%d ",t);
}
puts("");
while(!b.empty()){
int t=b.top();
b.pop();
printf("%d ",t);
}
puts("");
while(!c.empty()){
int t=c.top();
c.pop();
printf("%d ",t);
}
puts("");
priority_queue<pair<int,int> >d;
d.push({1,2});
d.push({1,3});
d.push({2,5});
while (!d.empty()){
cout << d.top().first << ' ' << d.top().second << '\n';
d.pop();
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct tmp1{
int x;
tmp1(int a) {x = a;}
bool operator<(const tmp1& a) const {
return x < a.x;
}
};
struct tmp2{
bool operator() (tmp1 a, tmp1 b) {
return a.x < b.x;
}
};
int main(){
tmp1 a(1);
tmp1 b(2);
tmp1 c(3);
priority_queue<tmp1> d;
d.push(b);
d.push(c);
d.push(a);
while (!d.empty()) {
cout << d.top().x <<" ";
d.pop();
}
cout << endl;
priority_queue<tmp1, vector<tmp1>, tmp2> f;
f.push(c);
f.push(b);
f.push(a);
while (!f.empty()) {
cout << f.top().x <<" ";
d.pop();
}
return 0;
}
8. set 用法
定义
set 容器中元素有序且不会重复,可以进行元素的快速查找、插入和删除。set 是基于红黑树实现的,事件复杂度 log n。
函数方法
| 函数 | 说明 |
|---|
| size() | 返回 set 容器中的元素数量 O(1) |
| empty() | 检查容器是否为空 O(1) |
| begin()/end() | 返回指向头部/尾部的迭代器 O(1) |
| clear() | 删除所有的元素 O(N) |
| insert() | 插入元素 O(log N) |
| find() | 查找某个元素,返回对应迭代器 |
| count() | 查找某个元素的出现次数 |
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int>s;
set<int>a={1,2,3};
for(int i=10;i>=0;i--){
s.insert(i);
}
int mmin=*s.begin();
int mmax=*(--s.end());
printf("%d %d\n",mmin,mmax);
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++){
printf("%d ",*it);
}
printf("\n");
s.erase(5);
s.erase(s.begin());
for(auto it:s){
printf("%d ",it);
}
printf("\n");
s.erase(--s.end());
for(auto it:s){
printf("%d ",it);
}
printf("\n");
s.clear();
printf("%d\n",s.size());
return 0;
}
9. multiset 用法
multiset 与 set 类似,但允许元素重复。
10. bitset 用法
补充知识:随机数
1. rand()
rand() 产生的是伪随机数字,每次执行时是相同。rand() 产生的随机数在每次运行的时候都是与上一次相同的。若要不同,用函数 srand() 初始化它。可以利用 srand((unsigned int)(time(NULL)) 的方法,产生不同的随机数种子,因为每一次运行程序的时间是不同的。
2. srand()
srand() 用来设置 rand() 产生随机数时的随机数种子。参数 seed 必须是个整数,如果每次 seed 都设相同值,rand() 所产生的随机数值每次就会一样。
- 给 srand() 提供一个种子,它是一个 unsigned int 类型;
- 调用 rand(),它会根据提供给 srand() 的种子值返回一个随机数 (在 0 到 RAND_MAX 之间);
- 根据需要多次调用 rand(),从而不间断地得到新的随机数;
- 无论什么时候,都可以给 srand() 提供一个新的种子,从而进一步"随机化"rand() 的输出结果。
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main() {
srand((unsigned)time(NULL));
for(int i = 0; i < 10;i++ ) cout << rand() << '/t';
cout << endl;
return 0;
}
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown 转 HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
- HTML 转 Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online