vector
vector 可理解为变长数组,它的内部实现基于倍增思想。
前置芝士
设 nnn,mmm 为 vector 的实际长度和最大长度。
向 vector 加入元素前,若 n=mn=mn=m,则在内存申请 2m2m2m 的连续空间,并把内容转移到新的地址上(同时释放旧的空间),再执行插入。从 vector 中删除元素后,若 n≤m4n \leq \dfrac{m}{4}n≤4m,则释放一半的空间。
vector 支持随机访问,即对于任意的下标 0≤i<n0 \leq i < n0≤i<n,可以像数组一样用 [i][i][i] 取值。
但它不是链表,不支持在任意位置 O(1)O(1)O(1) 插入。为了保证效率,元素的增删一般应该在末尾进行。
声明
#include <vector>
vector<int> a;
vector<int> b[233];//第一维长233,第二维长度动态变化
struct rec{};
vector<rec> c;
常用操作
vector<int> a;
a.empty();//返回一个bool类型,表明a是否为空
a.resize(10);//将a的元素个数调整为10,多删少补,值随机
a.resize(10,2);//将a的元素个数调整为10,多删少补,值为2
a.reserve(100);//将a的容量扩展为100
a.swap(b);//将a和b中的元素整体交换
reverse(a.begin(),a.end());//将元素翻转,逆序排列
a.size();//返回vector的实际长度(包含的元素个数)
a.clear();//把vector清空
a.back()//返回尾
a.front();//返回首
a.insert(a,begin()+i,qwq);//在第i个元素后面插入qwq
a.push_back(qwq);//尾部插入qwq
a.pop_back();//删除尾
a.at(i);//访问i号元素
a.erase(a.begin()+i);//删除第i+1个元素
a.erase(a.begin()+i,a.end()+j);//删除区间[i,j-1]
map
map 容器是一个映射表(key-value型),其内部实现是一棵红黑树。
map 的 key 和 value 可以是任意类型。
map 容器经常被当作 Hash 表使用,但是操作的时间复杂度为 O(logn)O(\log n)O(logn),略慢于传统Hash表。
常用操作
-
size、empty、clear、begin、end、countint gg=h.count(123);//由于map中的key值不能重复,所以gg只有可能是1或0 h.clear();//清空map里的所有key值对 h.empty();//返回1或0 //h.begin()和h.end()要搭配迭代器使用,举个栗子 for(it=h.begin();it!=h.end();it++) cout<<it->first<<it->second<<endl; cout<<*it; -
h.find(x):在变量名为h的map中查找 key 为 xxx 的二元组。 -
insert、erase -
搭配迭代器
map<int,int> h; h.insert(make_pair(1,2)); h.insert(pair<int,int>(6,7)); map<int,int>::iterator it=h.begin(),itlow,itup; itlow=h.lower_bound('b');//itlow指向大于等于‘b’的第一个元素 itup=h.upper_bound('d');//同理,指向大于‘d’键值的第一个元素 pair<int,int> p=*it; h.erase(it);h.erase(make_pair(2,3)); -
[]操作h[key]返回key映射到的value的引用,时间复杂度为 O(logn)O(\log n)O(logn)。还可以对
h[key]进行赋值操作,改变key对应的value。若查找的
key不存在,执行h[key]后,h会自动新建一个二元组(key,zero),zero表示一个广义零值,如整数 000,空字符串NULL等。强烈建议在
[]操作查询之前,先用find检查key的存在性。
其他 map
multimap:自动排序,但是支持存储多个 key 相同的键值对
unordered_map :内部是哈希表,不会根据 key 自动排序
杂记
对于 map 来说,一个 key 可以对应多个 value(新的 value 会覆盖旧的),但是一个 value 只能对应一个 key。
queue
和优先队列类似,基本操作如下:
queue<int> q:建立一个队列q,其内部元素类型是int。q.push(a):将元素a插入到队列q的末尾。q.pop():删除队列q的队首元素。q.front():查询q的队首元素。q.back():查询q的队尾元素。q.size():查询q的元素个数。q.empty():查询q是否为空。
priority_queue
优先队列,就是一种容器,默认它的第一个元素即堆顶为最大值。
priority_queue 可以理解为一个大根二叉堆~~(然鹅这东西我也不会)~~。
常用操作
-
q.push(x):把元素插入堆,时间复杂度为 O(logn)O(\log n)O(logn) -
q.pop():删除堆顶元素(即最大值) -
int x=q.top:查询堆顶元素(即最大值)
定义
-
从大到小(大顶堆):
priority_queue<int> q或priority_queue<int,vector<int>,less<int> > q -
从小到大(小顶堆):
priority_queue<int,vector<int>,greater<int> > q;
注意:最后的空格:> >
结构体与优先队列
需要重载运算符 <,举个栗子:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
friend bool operator < (node a,node b)
{
return a.x>b.x;
}
}gg;
int main()
{
priority_queue<node> q;
for(int i=1;i<=3;i++)
cin>>gg.x>>gg.y,q.push(gg);
cout<<q.top().x<<q.top().y;
return 0;
}
然后就可以像正常的优先队列一样使用啦(上面的代码建立的是小顶堆)!
当然我们还可以结构体外重载运算符:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
}gg;
bool operator < (node a,node b)
{
return a.x>b.x;
}
int main()
{
priority_queue<node> q;
for(int i=1;i<=3;i++)
cin>>gg.x>>gg.y,q.push(gg);
cout<<q.top().x<<q.top().y;
return 0;
}
set
set就是数学上的集合——每个元素最多只出现一次。和sort一样,自定义类型也可以构造 set,但同样必须定义“小于”运算符。
头文件:<set>
常用操作
set<int> ds:建立一个名字叫做 ds 的、元素类型为int的集合。ds.insert(x):在集合中插入一个元素,如果这个元素已经存在,则什么都不干。ds.eraase(x):在集合中删除元素 xxx,如果这个元素不存在,则什么都不干。ds.erase(it):删除集合中地址为 it 的元素。ds.end():返回集合中最后一个元素的下一个元素的地址。配合其他方法进行比较,以确认某个元素是否存在。ds.find(x):查询 xxx 在集合中的地址,如果这个数不存在,则返回ds.end()。ds.lower_bound(x):查询不小于 xxx 的最小的数在集合中的地址,如果这个数不存在,则返回ds.end()。ds.upper_bound(x):查询大于 xxx 的最小的数在集合中的地址,如果这个数不存在,则返回ds.end()。ds.empty():如果集合是空的,则返回 111,否则返回 000。ds.size():返回集合中元素的个数。
multiset
性质
- 元素按顺序排列,默认升序
- 不去重(与
set不同)
常用操作
multiset<int>q;
//定义一个multiset,尖括号里写类型
//如果是自定义类型,需要重载小于号
q.insert(x);
//插入一个数 x
q.clear();
//清空
q.erase(x);
//删除容器中的所有值为 x 的数
q.erase(it);
//删除容器中迭代器it指向的元素
q.empty();
//返回bool值,如果容器为空返回true,否则返回false
q.size()
//返回元素个数
q.begin();
//返回首个元素的迭代器
q.end();
//返回最后一个元素的下一个位置的迭代器
q.count(x);
//返回容器中 x 的个数
q.find(x);
//返回容器中第一个x的位置(迭代器),如果没有就返回q.end()
rope
rope 是一种神奇的 STL,使用 rope 可以轻松地实现可持久化数据结构。rope 可以在 O(1)O(1)O(1) 的时间内拷贝历史版本。rope 的本质其实是一种块状链表。
对于 rope 的使用,我们必须加上这两行代码:
#include <ext/rope>
using namespace __gnu_cxx;
rope 的定义如下:
rope<char> a,b;//rope<char> is equal to crope
rope<int> s[10005];
rope 的常用操作与 STL 中的其他容器十分类似,具体如下:
rope<int> x;
x.push_back(x);//在末尾加x
x.insert(pos,r);//在pos后加r
x.erase(pos,r);//从pos开始删除r个元素
x.substr(pos,r);//从pos开始拷贝r个元素
x.replace(pos,r);//从pos开始把后面所有元素都替换成r
x.at(r);x[r]//访问x的第r个元素
x.copy(pos,len,r);//从pos开始把后面len个元素替换成r
x.pop_back();
x.delete(r,len);//从第r个元素开始清除len个元素
x.replace(pos,len,r);//从pos开始把后面len个元素替换为r
x.size();//返回长度
x.max_size;//返回最大长度
itb=multable_begin();//指向起点的迭代器
ite=multable_end();//指向终点的迭代器
对于一些常用操作,时间复杂度如下:
-
push_back()、pop_back()、delete()、substr()、replace():O(logN)O(\log N)O(logN) -
insert():最好 O(logN)O(\log N)O(logN),最坏 O(N)O(N)O(N)
804

被折叠的 条评论
为什么被折叠?



