又爱又恨的STL:
文章目录
STL(标准模板库)
STL组成的六部分:算法、容器、迭代适配器、迭代器、仿函数、空间配制器。
容器:
- 简单容器:pair
- 序列容器:vector,list,forward_list(单向链表),deque(双端队列),arry(C++14)
- 容器适配器:queue,priority_queue,stack
- 关联容器:set,multiset,map,multimap,(unordered_set,unordered_multiset,unordered_map,unordered_multimap)
- .其他容器:bitset, valarry.
vector-变长数组
-
底层实现:数组
-
头文件:
#include <vector>
-
定义
vector<typename> name;
//可以看成一维数组vector<vector<typename> > name;
// 可以看成二维数组
-
定义vector数组:
vector<typename> Arrayname[arrySize];
//可以看成二维数组,但不同于vector<vector<typename> >
的是,一维的长度已经固定了。
-
访问:
- 通过下标访问:
name[index];
- 通过迭代器(iterator)访问,这里用循环来解释:
for(vector<typename>::iterator it = name.begin(); it!=name .end();it++) { cout<<*it<<end;;}
//此时*it是vector里的元素。或for(auto it:name){cout<<it<<" "}
//基于范围的for循环。
- 通过下标访问:
-
常用函数:
函数名 push_back()
pop_back()
size()
clear()
insert(it,x)
功能 尾插 尾删 长度 清空 向迭代器it处插入元素x 时间复杂度 O(1) O(1) O(1) O(n) O(n) -
erase()
- erase(it) 删除目前迭代器指向 的元素
- erase(first,last) 删除区间内的元素PS(first与last都是迭代器)
- 时间复杂度O(n)
set-内部自动有序且不含重复元素
- 底层实现:红黑树
- 头文件:
#include<set>
- 定义set:
set<typename >name
- 访问:只通过迭代器来访问。
for(set<typename>::iterator it = name.begin(); it!=name .end();it++) { cout<<*it<<end;;}
或for(auto it : name){cout<<it<<" "}
//此时*it是set里的元素。 - 常用函数:
函数名 | insert() | find(value) | size() | clear() |
---|---|---|---|---|
功能 | 插入 | 返回对应值为value的迭代器 | 容器长度 | 清空容器 |
时间复杂度 | O(logN) | O(logN) | O(1) | O(N) |
name.erase(it)
删除当前迭代器it指向的值。时间复杂度O(1)
name.erase(value)
删除value这个值。时间复杂度O(logN)
name.erase(first,last)
删除区间[first,last)内的元素。时间复杂度O(last-first).first与last都为迭代器
string-字符串
- string 读入可以用cin,输出可以用cout,也可以用
printf("%s",ss.c_str());
- 头文件:
#include<string>
- 定义:
- 一维:
string str;
- 二维:
string str[maxx];
- 一维:
- 访问:
- 通过下标访问
- 通过迭代器访问
- 常用技巧
clear() | += | ==、!=、<、<=、>、>= | length()/size() | substr(pow,len) |
---|---|---|---|---|
清空 | 拼接赋值 | 通过字典序来比较大小 | 长度 | 返回从pos号位开始,长度为len的子串 |
O(1) | O(1) | O(len) |
insert()
insert(pos,string)
在pos位置插入stringinsert(it1,it2,it3)
在it1位置上插入[it2,it3)区间的字符串。其中it1,it2,it3均为迭代器
erase()
erase(it)
删除it指向的字符erase(first,last)
删除区间[first,last)所有的元素erase(pos,len)
删除从pos开始的len长度的字符个数
find()
find(str2)
找到子串第一次出现的位置,若不是,返回string::npos ^ 1find(str2,pos)
从str的pos开始开始匹配str2- 时间复杂度为:O(nm)。其中n、m分别是str和ser2的长度
repalce()
replace(pos,len,str2)
把str从pos号位开始,长度位len的子串替换为str2replace(it1,it2,str2)
把str的迭代器[it1,it2)范围的子串替换为str2- 时间复杂度为:O(str.size())。
map-键值对(key-value)
-
底层实现:红黑树
-
头文件:
#include<map>
-
定义:
map<typename1,typename2 > name
-
访问:
-
通过下标访问
-
通过迭代器访问
for(map<typename1, typename2>::iterator it = name.begin(); it != name.end(); it++{ it->first; //访问键 it->second;//访问值 }
-
-
常用函数:
函数名 | find(key) | size() | clear() |
---|---|---|---|
功能 | 返回key的映射的迭代器 | 长度 | 清除 |
时间复杂度 | O(logN) | O(1) | O(N) |
erase()
erase(it)
删除it指向的元素。O(1)erase(key)
删除键中为key的值。O(logN)erase(first,last)
删除[first,last)区间元素。O(last-first)
queue-队列
- 底层实现:用list或deque(默认)实现,封闭头部即可
- 头文件:
#include<queue>
- 定义:
queue<typename> name
- 访问:
front()
队首back()
队尾
- 常用函数
函数名 | push() | front()/back() | pop() | empty() | size() |
---|---|---|---|---|---|
功能 | 入队 | 取队头/队尾 | 队头出队 | 队列判空 | 判断队中的元素 |
时间复杂度 | O(1) | O(1) | O(1) | O(1) | O(1) |
priority_quque-优先队列(自动排序的队列)
- 底层实现:以vector为底层容器,堆为处理规则来管理底层容器
- 默认为数字大的优先级高
- 头文件:
#include<queue>
- 定义:
priority_queue< typename > name;
- 访问:
name.top()
- 常用函数
函数名 | push() | top() | pop() | empty() | size() |
---|---|---|---|---|---|
功能 | 入队 | 取队头 | 队头出队 | 队列判空 | 判断队中的元素 |
时间复杂度 | O(1) | O(1) | O(1) | O(1) | O(1) |
-
优先级设置
-
基本数据类型
priority_queue<int > q; priority_queue<int,vector<int>,less<int> > q;//数字大的优先级大 priority_queue<int,vector<int>,greate<int> > q;//数字小的优先级大 注:vector<int>是来承载底层heap的容器。less<int>与greater<int>是对第一个参数的比较类。
-
结构体
-
将重载放到结构体内
struct student{ string s_id; int s_grade; friend bool operator < (student s1,student s2){ return s1.s_grade < s2.s_grade;//s_grade大的优先级高 } } priority_queue<student> q;
-
将重载放到结构体外
struct cmp{ bool operator (const student &s1,const student &s2){ return s1.s_grade > s2.s_grade; } } priority_queue<student,vector<student>, cmp> q;
-
-
stack-栈
-
底层实现:用list、deuqe(默认)或vector实现,封闭头部即可
-
头文件:
#include<stack>
-
定义:
stack<typename > name;
-
访问:使用
top()
来访问栈顶元素 -
常用函数:
函数名 push()
top()
pop()
empty()
size()
功能 入栈 取栈顶元素 出栈 判断栈是否为空 当前栈的长度 时间复杂度 O(1) O(1) O(1) O(1) O(1)
pair-对
- 头文件:
#include<utility>
- 定义:
pair<typename1,tepename2 > name
- 访问:
name.first
/name.second
分别表示第一个元素和第二个元素。 - 常用技巧:
- 插入
- 用函数插入:
make_pair(name.first,name.sceond);
- 直接插入:
cin>>name.first>>name.sceond
- 用函数插入:
- 比较操作符^2 :比较规则是先比较first,first相同时再比较second。
- 插入
算法
sort()与stable_sort()
-
这里多说一下,数组排序就是从你指定的地址开始,在你给定的长度之前排序。但是string有点不一样,如果你像用数组那么使用,那便是你对string数组进行排序。当你要对单个的string进行排序时用法为:
sort(name[i].begin(),name[i].end())
-
sort()
:默认升序重新排序指定访问的元素。可重载-
用法:
-
sort(v.begin(),v.end(),less<int>())
//升序 -
sort(v.begin(),v.end(),greate<int>())
//降序 -
bool cmp(int a,int b){ return a > b; } sort(v.begin(),v.end(),cmp);
-
-
不稳定的排序
-
时间复杂度O(NlogN);
-
-
stable_sort()
:与sort类似,不过保留相等元素之间的顺序关系。可重载- 稳定的排序
- 时间复杂度:O(Nlog2(N))
random_shuffle()
- 对指定范围被的元素随机排序
- 时间复杂度O(1);
lower_bound()与upper_bound()
- 二分查找函数,返回的是迭代器
lower_bound():
- 用法:
lower_bound(v.begin(),v.end(),20)-v.begin();
//在vector里面查找第一个大于或等于20的下标 - 返回第一个大于或等于查找的数的地址。
- 用法:
upper_bound():
- 用法:
upper_bound(v.begin(),v.end(),20)-v.begin();
//在vector里面查找第一个大于20的下标 - 返回第一个大于查找的数的地址。
- 用法:
next_permutation()
- 全排列函数
- 用法
int x[3] = {3,2,1};
sort(a,a+3);
do {
cout<<x[0]<<" "<<x[1]<<" "<<x[2]<<endl;
}while(next_permutation(x,x+3));
- 时间复杂度:O(N!)
unique()
- 有序数组去重
- 用法:
unique(a,a+n)-a;
返回的是数组去重后的长度。 - 时间复杂度:O(N)
迭代器
可以看成是广义的指针,所以我们使用的时候要加上一个*。
iterator(默认容器为vector,名称为v)
-
最普通的迭代器,也最常用。
-
定义:
vector<typename>::iterator it ;
-
大多数我们使用迭代器就是为了遍历当前容器。
vector<typename>::iterator it; for(it = v.begin(); it != b.end(); it++) cout<<*it<<" ";//输出当前容器
-
C++11新特性
-
使用auto可以减少代码量,但只有编译器支持C++11才可以用
for(auto it : v) cout<<it<<" ";
-
reverse_iterator
- 反向迭代器
- 用法与iterator相反。
- 这里用循环演示一下:
for(vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)