常用 STL 整理
vector
可变长数组,变长是基于 倍增 的思想
系统为某一个程序分配空间时,有一个特点,
他所需的时间基本上与空间大小无关,只与申请次数有关
(即 100 和 1000 没区别,只和请求次数有关)
因此,vector的优化目标是,减少申请的次数(优化时间,可以浪费空间)
起初先申请一个 小的空间(例如32),当我们插入到边界的时候,就会申请到 64个空间
然后把 原来的32个元素copy过来,(每一次数组长度不够的时候,就把数组的长度*2,再把原来的
元素copy过来。
假设要申请 n 的数组,起初为 1 ,我们一共会copy 1 + 2 + 4 + 8....+5*10^5 == 10^6 ,
因此大概copy的操作是 10^6 ,均摊下来, 尾部插入的操作就是(O(1)) 的,随机插入是(O(n))
初始化
vector<typename> name;
vector<int> a(n); // 初始化大小为n的数组,0~n-1
vector<int> a(n,3); //初始化大小为n的数组,所有值均为3
vector<vector<int> > name; // 定义二维的vector,两维都能动态变长
vecotr<int> a[n]; // 第一维已经固定,第二维才是vector
访问
(1) 通过下标随机访问 范围是 0 ~ size() - 1
(2) 通过迭代器访问 iterator (类似于指针)
vector<int>::iterator it;
通过 *it 来访问元素//支持++,--
- 其中 v[i] 和 *(v.begin() + i) 是等价的
常用函数
push_back(); // 尾端插入 O(1)
pop_back(); // 尾端删除 O(1)
size(); // 返回元素个数 O(1) ,返回的是 unsigned 类型
clear(); // 虚假的清空 不能真正的清空元素个数,放弃使用,直接新定义一个重名的,当做清空
v = vector<int>(); // 真正的清空
insert(it,x); // 在迭代器 it 处,插入一个元素 x, O(n)
erase();// 删除单个元素 O(n)
erase(v.begin(),v.end());// 删除区间的元素 O(n)
// 支持比较运算,按字典序来比较
pair
可以看作一个内部有两个元素的结构体,元素类型任意指定
初始化
pair<typename1,typename2> p;// typename 可以为任意类型
pair<int,pair<int,int> > p; // pair支持多重嵌套
//临时构造pair
p = make_pair("123",123);
p = {"123",123}; // C++ 11 写法
访问
p.first; // 第一个关键字
p.second; // 第二关键字
用途
1.支持比较运算,排序的时候,以first为第一关键字,second为第二关键字
2.用来代替二元结构体及其构造函数
3.作为map的键值对来进行插入
string
C++ 封装好的字符串
初始化
string s = "123";
访问
c_str() 可以返回 string 类型的字符串存储的起始地址
通过迭代器访问 string::iterator it;
s[i]; // 像数组一样访问
常用函数
size() 与 length() 基本相同,O(1);
支持字典序比较 <=,<,>=,>....
insert(pos,string);// 在pos位置,插入string字符串 O(n)
erase();// O(n)
substr(pos,len); // 返回从 pos 开始,长度为 len 的字符串 O(len)
str1.find(str2); // 返回str2 在 str1 中第一次出现的位置,如果没有出现,返回 npos O(n^2)
string::npos;// 是一个常数 -1
replace(); // 区间替换字符串
+ // 拼接
queue
queue , push(),pop(),front()
push() 队尾插入
front() 返回队头元素
back() 返回队尾
pop() 弹出队头
没有clear() 操作
清空的时候,直接重新构造就行了 q = queue
();
priority_queue
// 优先队列,堆,默认是大根堆
小根堆的时候,直接插入负数,就可以变成小根堆 (黑科技
直接定义成小根堆
priority_queue<int,vector
,greater > heap;
stack
// 栈
O1
deque
// 双端队列,随机访问
加强版的 vector,有clear,支持随机寻址,速度很慢(一般不用,太慢了
front()
back()
push_back()
push_front()
pop_back(),pop_front()
set , multiset(可以插入重复元素),
log n
不能插入重复元素(插入的话,会被忽略掉
insert()
find() // 如果不存在,返回end的迭代器
count() 返回某一个数的个数
erase()
(1) ,输入一个数x,删除所有的 x O(k + logn)
(2),输入一个迭代器
lower_bound() 返回大于等于 x 的最小的数
upper_bound() 返回 大于 x 的最小的数
不存在的话,返回end()
map,multimap
// 平衡树,基于平衡二叉树(红黑树 (平衡二叉树的一种)),hash
动态维护一个有序序列
全是log n,包括 ++,--
insert(x) 插入的数,是一个pair
erase() 输入的参数,是pair或者迭代器
find()
[] //像数组一样,用map,时间复杂度是 O(log n)
lower_bound,upper_bound
unordered_set,unodered_map,unordered_multiset,unordered_multimap // 基于hash表
和上面都是类似的,绝大多数操作都是 O(1) 的,都是无序的,
不支持 upper_bound,lower_bound
bitset// 压位,
例如 1024 bool 字节 需要 1024B = 1kb
比正常的 bool 数组省 8 位内存,
bitset利用了每一 个 bit
bitset<1000> s;
count() 返回有多少个 1
any() 返回是否至少有一个 1
none() 是否全为空
set() 把所有 位 置为 1
set(k,v) 将第k位,变成 v
reset() 把所有位 变成 0
flip() 等价于 ~
flip(k) 是把 第 k 位取反
list // 链表,用的不多
参考
《算法笔记》
《算法竞赛入门经典》
《算法竞赛进阶指南》