STL
系统为某一程序分配空间时,所需时间与空间大小无关,与申请次数有关。
1.vector
变长数组,倍增的思想(减少申请空间的次数,效率很高,刚开始是一个很小的数8,16,32, 等到存储完,不够了会成倍增加,像32变成64,然后把原来数组里面的内容复制下来)
头文件:
#include<vector>
函数:
size() 返回元素的个数 时间复杂度O(1)
empty() 返回是否为空,空返回true 不空返回false
clear() 清空
front()/back() 返回第一个数/返回最后一个数
push_back() / pop_back() 向vector的最后增加一个数 / 把最后一个数删掉
begin() / end() 第0个数 / 最后一个数的后面一个数
支持随机寻址,跟数组一样,就是比如数组 a[100] 我可以直接使用a[5]找到这个数,而不是从1遍历到5才找到。
支持比较运算,按字典序
代码:
vector<int> a(10, 3); // 定义长度为10的vector,其中每个数都是3
// 所有容器都有,时间复杂度是o(1)
a.size(); // 返回vector的里面元素的个数
a.empty(); // 看是不是空的,空的返回true,不是就是false
// 遍历vector{
for(int i = 0; i < n; i ++ ) a.push_back();
for(int i = 0; i < a.size(); i ++ ) cout << a[i] << " ";
cout << endl;
// vector的迭代器遍历 a[0] a[a.size()]
for(vector<int>::iterator /* 这一坨可以写成auto, */ i = a.begin(); i != a.end(); i ++ )
cout << *i << ' '; // 迭代器可以看成指针,所以取值要加*
// c++里的范围遍历,代码短效率快
for(auto x : a) cout << x << ' ';
cout << endl;
// 支持比较运算
vector<int> a(4, 3), b(3, 4); // a < b按字典序比较
2.pair
可以存储一个二元组,前后两个变量可以任意, 可以看成一个有两个变量的结构体,还实现了比较函数,省代码。
头文件:
可以直接在#include<iostream>里用
函数:
first 第一个元素
second 第二个元素
支持比较运算,以first为第一关键字,以second为第二关键字(字典序)
代码:
pair<int, string> p; // 定义
pair<int, pair<int, int>>p; // 可以用pair存储三个属性
p = make_pair(10, "jyy"); // 初始化
p = {20, "abc"};
3.string
c++把字符串进行的封装
可以用
头文件:
#include<string>
函数:
size() / length() 返回字符串长度
empty() 是否为空
clear() 清空
substr() 返回某个字串
c_str() 返回存储字符串数组的起始地址
代码:
//定义
string a = "jyy"; // 定义,初始化
a += "abc"; // 在某个字符串后面添加个字符串
a += 'c';
cout << a.substr(1, 3) << endl;
/* substr(起始位置,字串长度) 若是3超过了数组长度则输出到最后一个字母为止 其他语言好像都是起始位置和截至位置,但是c++是子串长度*/
cout << a.substr(1) << endl;// 返回从1开始的整个子串
printf("%s\n", a.c_str());
// 用printf输出,c_str()返回存储字符串的字符数组的起始地址
4.queue
队列,队尾插入,队头弹出
头文件:
#include<queue>
函数:
size()
empty()
push() 向队尾插入一个元素
front() 返回队头元素
back() 返回队尾元素
pop() 弹出队头元素
没有clear函数
代码:
queue<int> q; // 定义
q = queue<int>(); // 因为没有clear函数,所以想要清空就重新定义一个新的就可以了
5.priority_queue
优先队列(用堆实现的),默认是大根堆
头文件:
#include<queue>
函数:
size()
empty()
push() 插入一个元素
top() 返回堆顶元素
pop() 弹出堆顶元素
没有clear函数
代码:
// 定义 默认大根堆
priority_queue<int> heap;
// 如何定义小根堆???
heap.push(-x); // 小技巧 1.向堆中插入一个数的时候插入负数,负数从大到小那正数就是从小到大了
priority_queue<int, vector<int>, greater<int>> heap; // 2.直接定义成小根堆,要多加两个参数
6.stack
栈
头文件:
#include<stack>
函数:
size()
empty()
push() 向栈顶插入一个元素
top() 返回栈顶元素
pop() 弹出栈顶元素
没有clear函数
7.deque
双端队列,加强版的vector
头文件:
#include<deque>
函数:
size()
empty()
clear()
front() 返回第一个元素
back() 返回最后一个元素
push_back() / pop_back() 向最后插入一个元素 / 弹出最后一个元素
push_front() / pop_front() 向队首插入一个元素 / 从队首弹出一个元素
begin() / end()
支持随机寻址
优点:功能十分强大,各种功能
缺点:效率低,比一般的慢好几倍,所以用的不多
8.set, map, multiset, multimap
基于平衡二叉树(红黑树),本质上是动态维护有序序列
头文件:
#include<set>
函数:
坏处是跟增删改查的操作是O(logn)的
size()
empty()
clear()
begin() / end() 支持++, -- 操作,返回前驱和后继(有序序列里的前驱指前面一个数,后继是后面一个数) O(logn)
set/multiset 中
insert() 插入一个数
find() 查找一个数,如果不存在返回end这个迭代器
count() 返回某一个数的个数,set中只有0和1两种情况,multiset中有几个返回几个
erase()(在set里没有区别,在multiset中x有多个,删x,所有x都删了,删迭代器,只删迭代器)
(1) 输入是一个数x,删除所有x 时间复杂度O(k + logn) k是x的个数
(2)输入一个迭代器,删除这个迭代器
lower_bound(x) 返回大于等于x的最小的数的迭代器,不存在返回end
upper_pound(x) 返回大于x的最小的数的迭代器,不存在返回end
map / multimap 有两个变量,存的映射
insert() 插入的数是一个pair
erase() 输入的参数是pair或者迭代器
find() 查找一个数,如果不存在返回end这个迭代器
我们可以像用数组一样用map但是时间复杂度是O(logn) 数组用下标是O(1)
map<string, int> a; // 定义
a["jyy"] = 1;// jyy就映射到了1
cout << a["jyy"] << endl; // 输出 就是1
9.unordered_set, unordered_map, unordered_multiset, unordered_multimap
哈希表
头文件:
#include <unordered_set>
与上面类似,增删改查的时间复杂度是O(1)
不支持 lower_bound() / upper_bound() 以及迭代器的++, --操作
8和9的对比,
9不支持和排序有关的操作,但是跟增删改查的操作是O(1)的
8支持根排序有关的操作,坏处是跟增删改查的操作是O(logn)的
10.bitset
压位
头文件:
#include<bitset>
像长度是1024 boll型 1024字节,要开1024B内存,但是压位后只需要开128B内存就行了, 之前每个状态需要1个字节,1024个状态记录需要1024个字节,但现在每个状态只需要1位,1024个状态只需要128个字节。 可以省8位空间
代码:
bitset<10000> s; //定义 bitset<个数>
支持各种位运算
~, &, |, ^, >>, <<, ==, |=
[]可以取出来某一位是0是1
函数:
像这些函数没必要记,用到了查就行
count() 返回有多少个1
any() 判断是否至少有一个1
none() 判断是否全为0
set() 把所有位置成1
set(k, v) 将第k位变成v
reset() 把所有位变成0
flip() 等价于 ~
flip(k) 把第k位取反
https://cplusplus.com/内含最权威的最新的c++的各种语法,hh