简单的介绍一下STL的用法 看起来内容很多 只要遇到对应的题写个几题 很容易就熟能生巧了
为何cpp是竞赛使用最为广泛的语言呢 1 速度快 2 STL强大 因此掌握好STL 一定能让你做题的效率更上一层楼
Vector
介绍
你可以把vector当做一个动态的数组 长度可扩容 且在main里开vector是开在堆空间的
初始化
//需要头文件 #include <vector>
vector<int> q;
vector<node> q;
//定义长度
vector<int> q(n);
vector<int> q(n, 0);//定义长度并赋值
vector<int> a(n);
vector<int> b(a); //拷贝a到b
vector<int> q[5]; //行固定为5 列可以扩容
vector<vector<int> > q;//二维均可扩容
vector<vector<int> > q(n, vector<int>(m)); //初始化行为n 列为m
遍历
直接访问下标(不越界时) cout << q[3];
for(int i = 0; i < q.size(); i++)
cout << q[i] << ' ';
for(auto x : q) cout << x << ' ';
库函数
q.front(); 返回第一个元素
q.pop_back(); 删除最后一个元素
q.push_back(); 在末尾加入一个元素
q.size(); 返回容器长度
q.clear(); 清空容器
q.insert(it, x); 在迭代器it处插入x eg. insert(2, 1) 在q[2]插入1
sort(q.begin(), q.end()); 容器的始末地址
q.empty(); <==> !q.size() 判空 空->真
Stack
介绍
特点:先进后出,后进先出
初始化
#include <stack>
stack<int> stk;
stack<node> stk;
遍历
栈不能直接遍历 只能一个一个出栈
while(stk.size()) res[i ++] = stk.top(), stk.pop();
数组模拟栈 可以跑得更快吧
int stk[100];
int cnt = 0;
void push(int x) {stk[++ cnt] = x;}
void pop() {cnt --;}
int top() {return stk[cnt];}
库函数
stk.push(); 将元素压入栈顶
stk.top(); 得到栈顶元素
stk.pop(); 删去栈顶元素
stk.size(); 返回栈内元素个数
stk.empty(); 判空
Queue
介绍
队列是一种先进先出的数据结构
初始化
#include <queue>
queue<int> q;
数组模拟队列
int q[100];
int hh = 0, tt = -1; //队头和队尾
void push(int x) {q[tt ++] = x;}
void pop() {if(tt >= hh) ++ hh;}
int front() {return q[hh];}
bool empty() {return tt >= hh;}
库函数
q.push() 在队尾插入一个元素
q.pop(); 在队头删除一个元素
q.front(); 返回队头
q.back(); 返回队尾
q.size(); 长度
q.empty(); 判空
Deque
介绍
双端队列 跟队列的区别就在于 双端队列的头和尾都可以进行插入和删除操作
初始化
#include <deque>
deque<int> dq;
双端队列可以排序,等同vector写法
库函数
push_back()/push_front(); 队尾插入队头插入
pop_back()/pop_front(); 删尾删头
back()/front(); 获得尾和头元素
erase(it); 删去it所指元素
erase(it fisrt, it last); 删去[fisrt, last)所指元素
empty(); 判空
size(); 长度
clear(); 清空
Priority_queue
介绍
底层由堆来实现 可以在每次增删改查的时候维护序列有序 时间复杂度是nlgn
初始化
#include <queue>
priority_queue<int> q;(大根堆)
priority_queue<int, vector<int>, greater<int> > q;(小根堆)
自定义排序
greater<xx> 表示数字小的优先级大
less<xx> 表示数字大的优先级大
cmp可以来代替greater等放在第三位置
如果是结构体的话 可以重载来更改规则
但是有一点很重要 就是优先队列的排序规则跟sort是相反的 //被狠狠地坑过
库函数
top(); 队头
push(); 压入
pop(); 删头
size(); 长度
empty(); 判空
Map
介绍
对于map 我们可以理解他为函数中的映射 且为单射 每个key对应一个value
对于map中的元素 会被自动排序 以key的顺序来小到大排序 所以插入查询的复杂度是nlgn
还有两种map
unordered_map 只做映射不做排序 所以插入和查询都是O1的 但是会被卡 也就是说 在时间宽裕的情况下最好使用map
multimap 一个键对应多个值的映射 可重版map
初始化
#include <map>
map<int, int> mp;
map<string, int> mp;
访问
mp[a] = b;
insert({xxx, xxx});
下标访问 cout << mp[x] << endl;
遍历
auto it = mp.begin();
while(it != mp.end()) //for(; it != mp.end(); it ++)
{
cout << it->first << ' ' << it->second << '\n';
it ++;
}
for(auto x : mp)
cout << x.first << ' ' << x.second << '\n';
for(auto [k, v] : mp) //C++17
cout << k << ' ' << v << '\n';
库函数
mp.find(key) 返回键为key的迭代器 若不存在 返回mp.end() 一般用于定位
mp.erase(it) 删除迭代器it所指的键与值O(1)
mp.erase(key) 根据映射来删除键与值O(lgn)
mp.erase(first, last) 删除左闭右开区间内的迭代器所指值O(n)
mp.size() 长度
mp.clear() 清空O(n)
mp.insert() 插入 需要构造键值对
mp.empty() 判空
mp.begin() 返回指向mp的第一个迭代器(地址)
mp.end() 返回指向mp尾部的结束迭代器(主要是最后一个元素的下一个地址)
mp.rbegin() 返回指向mp的最后一个迭代器(地址)
mp.rend() 返回指向mp的第一个迭代器(地址)
mp.count(key) 判断key是否存在,存在真
Set
介绍
set表示一个集合 该容器内元素不会重复 并自动排序 由于需要排序 所以插入和查询的复杂度是nlgn
其他set
mulitset: 可重集合 依然有序
unordered_set: 集合 且无序
unordered_mulitset: 可重集合 且无序
初始化
#include <set>
set<int> s;
访问
有无set存储的是集合 所以我们是不能通过索引来直接访问的
for(auto x : s)
cout << x << '\n';
想要访问单体的话 可以使用指针
eg 访问最后一个元素cout << *(--s.end()) << '\n';
库函数
s.begin(); 返回指向s的第一个迭代器(地址)
s.end() 返回指向s尾部的结束迭代器(主要是最后一个元素的下一个地址)
s.rbegin() 返回指向s的最后一个迭代器(地址)
s.rend() 返回指向s的第一个迭代器(地址)
s.clear(); 清空
s.empty(); 判空
s.insert(); 插入
s.size(); 长度
mp.erase(it); 删去当前迭代器所指元素
mp.erase(first, last); 删去区间[first, last)所指元素
s.find(); 查找某一元素 返回其迭代器 若不存在 则返回结束迭代器
s.lower_bound(); 返回大于等于k的第一个元素的迭代器
s.upper_bound(); 返回大于k的第一个元素的迭代器
Pair
介绍
你可以把pair当做两个元素的结构体 用于与其他数据结构组合
初始化
pair<string, int> p;
pair<string, int> p("CCPC", 1);
//p = {"CCPC", 1};
typedef pair<int, int> PII; typedef pair<string, int> PSI;
vector<PII> q
访问
PII p[20];
for(int i = 0; i < n; i++)
cout << p[i].first << ' ' << p[i].second;
String
介绍
string是字符串类 类似于char数组 但是在char数组的基础上添加了很多简便的用法
初始化
#include <string>
string s;
string s("ASASDFAS"); //直接生成s = "ASASDFAS"
string s("s", start, length); //pos默认为0 length默认为s.size() - pos
string s("123456", 1, 3); //s = "234"
string s(5, '2'); //s = "22222"
访问
可以直接输出整个字符串
cout << s;
也可以遍历输出单个字符
for(int i = 0; i < s.size(); i++)
cout << s[i] << ' ';
string比起字符数组的特性
可以直接用+拼接字符串
用比较符号可以直接比较大小(字典序) 或者判断相等
string的读入
cin >> s;
用cin读入字符串 遇到空格和回车就会结束
aaa ss dd
cin >> s;
s = "aaa";
getline(cin, s);
读入一行字符串
aaa ss dd
getline(cin, s);
s = "aaa ss dd";
!!!需要注意的是 若是多行读入 getline会吃下前一行输入的换行符 需要用getchar吃掉换行符
eg
2
a c m
Wrong:
cin >> n;
getline(cin, s);
s == "";
Right:
cin >> n;
getchar();
getline(cin, s);
s == "a c m";
当数据量特别大 但这题要用string处理的时候 可以加速一下读入输出
ios::sync_with_stdio(false);cin.tie(0);
!!!注意 当加速后 不能与scanf printf getchar getline()混用 只能使用cin&cout
库函数
s.size(); 长度
s.push_back(char); 在字符串后插入一个字符
s.insert(pos, char); 在pos位置插入字符
s.erase(it); 删去迭代器it所指元素
s.erase(first, last); 删去区间[first, last)内所指元素
s.erase(pos, length); 删去从索引pos开始的长度为length的字符串
s.clear(); 将s重置为"\0"
s.substr(pos, n); 截取从索引pos开始的n个字符
s.find(str, pos); 在索引pos位置(默认为0)开始 查找 字符串/字符 str
s.rfind(str, pos); 在索引pos位置(默认为s.size() - 1) 开始查找 str
//找到后返回其索引 而返回-1表示没有找到
Bitset
介绍
bitset是一个只能由0或1组成的数字 每个元素占用1bit
初始化
#include <bitset>
bitset<n> a; 长度为n 每一位默认为0
bitset<9> bs(12); 将12转化为二进制保存 在前面补0直至9位
bitset<10> bs("10101"); 保存字符串 并 补前导0
访问
与字符串很类似 可以直接输出或者用下标访问
特点
可以直接对bitset进行位运算操作
eg
bitset<4> a;
bitset<4> b;
a &= b;
a ^= b;
所学尚浅 若有错误 请指正 以免误人子弟 感谢观看