[0.x]前言

本文针对[杂项] Cpp STL - 图1[杂项] Cpp STL - 图2容器

参考书目:《算法竞赛进阶指南》

所有容器都前闭右开(类比声明了数组a[n]后调用a[n]属于越界行为)

[杂项] Cpp STL - 图3的迭代器相当于指针,语法类似,使用方式为???::iterator ??=???

目录

  • [0.x]前言
  • [1.x]vector
  • [2.x]queue/priority_queue
  • [3.x]deque
  • [4.x]set/multiset
  • [5.x]map
  • [6.x]bitset
  • [7.x]algorithm

[1.x]vector

[1.1]性质

  • 大小会随着元素的数量变化(节约空间)
  • 支持随机访问(支持下标访问
  • 不支持[杂项] Cpp STL - 图4#card=math&code=O%281%29&id=EMAjz)插入

[1.2]声明

  1. #include<vector>//头文件
  2. using std::vector;
  3. vector<int> a;//a[i]中i所在的维动态伸缩
  4. vector<int> b[10];//b[i][j]中j所在的维动态伸缩
  5. //其中<int>可以换成<bool>/<char>/<string>/....且支持结构体

[1.3.x]操作

[1.3.1]size/empty
  1. cout << "vector型变量a的长度为" << a.size();
  2. if(a.empty()){
  3. cout << "vector型变量a为空";
  4. }else{
  5. cout << "vector型变量a不为空";
  6. }

[1.3.2]clear
  1. a.clear();//清空vector型变量a

[1.3.3]begin/end
  1. vector<int>::iterator it = a.begin();
  2. cout << "vector型变量a的第一个元素为" << *it;
  3. cout << "vector型变量a的第一个元素为" << a[0];//两行等效
  4. it = a.end();
  5. cout << "vector型变量a的最后一个元素为" << *--it;
  6. cout << "vector型变量a的最后一个元素为" << a[a.size()-1];//两行等效

[1.3.4]front/back

从front与begin类似,只不过一个返回元素一个返回迭代器,即*a.begin()a.front()等效,当然也等效于a[0]

而back与end略有区别,*--a.end()a[a.size()-1]a.back()等效(一般情况下)

  1. vector<int>::iterator it = a.begin();
  2. cout << "vector型变量a的第一个元素为" << *it;
  3. cout << "vector型变量a的第一个元素为" << a[0];
  4. cout << "vector型变量a的第一个元素为" << a.front();//三行等效
  5. it = a.end();
  6. cout << "vector型变量a的最后一个元素为" << *--it;
  7. cout << "vector型变量a的最后一个元素为" << a[a.size()-1];
  8. cout << "vector型变量a的最后一个元素为" << a.back();//三行等效

一般begin/end用于循环,而frontback只能用来返回顶部和底部。

[1.3.5]push_back/pop_back
  1. a.push_back(x);//把元素x插入到vector类型变量a的尾部
  2. a.pop_back;//把vector类型变量a尾部元素推出

[2.x]queue/priority_queue

[2.1]性质

  • 不支持随机访问
  • priority_queue满足元素有序(默认降序,堆顶部(看作大根二叉堆)为[杂项] Cpp STL - 图5),如果储存元素类型不属于数字类型或者**string**类型需要定义比较规则

[2.2]声明

  1. #include<queue>//头文件
  2. using std::queue;using std::priority_queue;
  3. queue<int> q1;//循环队列
  4. queue< pair<int,int> > q2;
  5. priority_queue<int> q3;//优先队列
  6. priority_queue< pair<int,int> > q4;

[2.3.x]操作

注意:由于循环队列和优先队列操作略有不同,所以以下变量q循环队列p_q优先队列

[2.3.1]push/pop
  1. q.push(x);//把元素x插入到queue类型变量q的尾部
  2. q.pop();//把队首元素弹出
  3. p_q.push(x);//把元素x插入到priority_queue类型变量p_q
  4. p_q.pop();//把堆顶元素弹出,即有序数列的首元素

[2.3.2]front/back & top
  1. cout << "queue型变量q的第一个元素为" << q.front();
  2. cout << "queue型变量q的最后一个元素为" << q.back();
  3. cout << "priority_queue型变量p_q的堆顶元素为" << p_q.top();

[3.x]deque

咕咕咕

[4.x]set/multiset

[4.1]性质

  • set储存有序集合
  • multist储存有序多重集合
  • 重载相关类似priority_queue
  • 迭代器只支持++--,时间复杂度都在[杂项] Cpp STL - 图6#card=math&code=O%28logn%29&id=kxjft),注意不要越界
  • 默认升序

[4.2]声明

  1. #include<set>
  2. using std::set;using std::multiset;
  3. set<int> s;
  4. multiset<int> ms;

[4.3.x]操作

注意s表示有序集合ms表示有序重复集合

[4.3.1]size/empty/clear

同理vector

[4.3.2]begin/end

同理priority_queue

[4.3.3]insert
  1. s.insert(x);//将元素x插入到集合s中,如果s中已经存在元素x则不变化
  2. ms.insert(x);//将元素x插入到集合ms中,如果s中已经存在元素x则再插入一个

[4.3.4]find

[杂项] Cpp STL - 图7#card=math&code=O%28logn%29&id=vICup)查找元素(返回迭代器),不存在则返回end()
有序多重集合返回第一个该元素的迭代器

  1. set<int>::iterator it = s.find(x);//*it为元素x,it为其迭代器
  2. multiset<int>::iterator it = ms.find(x);//*it为元素x,it为其迭代器

[4.3.5]lower_bound/upper_bound
  1. ?? = s.lower_bound(x);//O(logn)查找>=x的元素中最小的,返回迭代器(需要保证序列升序)
  2. ?? = s.upper_bound(x)//O(logn)查找>x的元素中最小的,返回迭代器(需要保证序列升序)
  3. ?? = ms.lower_bound(x)//O(logn)查找>=x的元素中最小的第一个,返回迭代器(需要保证序列升序)
  4. ?? = ms.upper_bound(x)//O(logn)查找>x的元素中最小的第一个,返回迭代器(需要保证序列升序)

如果需要应用在降序数列里,可以传输比较规则greater<int>()

[4.3.6]erase
  1. set<int>::iterator it;
  2. s.erase(it);//O(logn)删除it所指向的元素
  3. ms.erase(it);//O(logn)删除it所指向的元素
  4. int x;
  5. s.erase(x);//O(k+logn)删除所有x元素
  6. ms.erase(x);//O(k+logn)删除所有x元素

[4.3.7]count
  1. s.count(x);//返回集合s中等于x的元素的个数
  2. ms.count(x);//返回集合s中等于x的元素的个数

[5.x]map

[5.1]性质

  • 支持任意类型的key-value映射,但key需要有比较规则
  • 迭代器取值以后得到二元组pair<key_type,value_type>

[5.2]声明

  1. map<string,int> mp;//string类-int类映射,可以替换类型

[5.3.x]操作

[5.3.1]size/empty/clear/begin/end

同前

[5.3.2]insert/erase

同前
insert需要插入对应的二元组
erase可以是二元组或迭代器

  1. mp.insert(make_pair(x,y));//插入x-y的映射
  2. mp.erase(make_pair(x,y));//删除x-y的映射
  3. mp.erase(it);//删除it所指的映射

[5.3.3]find

同前,[杂项] Cpp STL - 图8#card=math&code=O%28logn%29&id=Xbtoy)查找目标为key

[5.3.4][]
  1. mp[str] = a;
  2. mp[ch] = flag;
  3. ...
  4. //使用[]前最好先用find查询是否存在映射,否则会浪费空间

[6.x]bitset

咕咕咕

[7.x]algorithm

注意:以下操作都作用在序列上,都在前闭后开区间[杂项] Cpp STL - 图9#card=math&code=%5Bl%2Cr%29&id=GauxF)中的元素进行操作

[7.1.x]操作

[7.1.1]reserve
  1. vector<int> a;
  2. reverse(a.begin(),a.end());//翻转vector类型变量a
  3. int b[100];
  4. reverse(b+1,b+n+1);//翻转数组b中1~n的序列

[7.1.2]unique
  1. vector<int> a;
  2. cout << "vector型变量a去重后的元素个数为" << unique(a.begin(),a.end()) - a.begin();
  3. int b[100];
  4. cout << "数组b去重后的元素个数为" << unique(b+1,b+n+1) - (b+1);//去重后元素存放在下标1~n,未去重的部分保留

[7.1.3]random_shuffle
  1. vector<int> a;
  2. random_shuffle(a.begin(),a.end());//打乱vector类型变量a
  3. int b[100];
  4. random_shuffle(b+1,b+n+1);//打乱数组b中1~n的序列

[7.1.4]next_permutation/prev_permutation
  1. //按照字典序输出全排列(起始数列升序)
  2. do{
  3. for(int i = 1;i <= n;i++){
  4. cout << a[i] << " ";
  5. }cout << endl;
  6. }while(next_permutation(a+1,a+n+1));
  7. //按照字典序倒着输出全排列(起始数列降序)
  8. do{
  9. for(int i = 1;i <= n;i++){
  10. cout << a[i] << " ";
  11. }cout << endl;
  12. }while(prev_permutation(a+1,a+n+1));

[7.1.5]sort

[7.1.6]lower_bound/upper_bound

同前,需要数列升序

如果需要应用在降序数列里,可以传输比较规则greater<int>()

  1. int i = lower_bound(a+1,a+n+1,x) - a;//输出升序数组a中1~n中>=x的第一个数的下标
  2. int j = upper_bound(a+1,a+n+1,x) - a;//输出升序数组a中1~n中>x的第一个数的下标
  3. cout << "vector型变量b中大于等于x的最大整数" << *lower_bound(b.begin(),b.end(),x) << endl;
  4. cout << "vector型变量b中小于等于x的最大整数" << *--upper_bound(b.begin(),b.end(),x) << endl;

[7.1.7]unique

unique函数用于去重,使用该函数之前一般先排序。下面只讲不涉及迭代器的常规用法。

  1. std::sort(a+1,a+n+1); // 先决条件,排序
  2. int cnt = std::unique(a+1,a+n+1) - a - 1; // 实现去除重复元素的同时达到了得到去重后元素种树cnt的效果
  3. /*
  4. 运行前:
  5. a = {0,1,2,3,3,4} , n = 5;
  6. 运行后:
  7. a = {0,1,2,3,4,4} , n = 5 , cnt = 4;
  8. */