STL容器相关笔记

vector

vector 可理解为变长数组,它的内部实现基于倍增思想。

前置芝士

nnnmmmvector 的实际长度和最大长度。

vector 加入元素前,若 n=mn=mn=m,则在内存申请 2m2m2m 的连续空间,并把内容转移到新的地址上(同时释放旧的空间),再执行插入。从 vector 中删除元素后,若 n≤m4n \leq \dfrac{m}{4}n4m,则释放一半的空间。

vector 支持随机访问,即对于任意的下标 0≤i<n0 \leq i < n0i<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(log⁡n)O(\log n)O(logn),略慢于传统Hash表。

常用操作

  • sizeemptyclearbeginendcount

    int 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):在变量名为 hmap 中查找 key 为 xxx 的二元组。

  • inserterase

  • 搭配迭代器

    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(log⁡n)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

和优先队列类似,基本操作如下:

  1. queue<int> q:建立一个队列q,其内部元素类型是int
  2. q.push(a):将元素a插入到队列q的末尾。
  3. q.pop():删除队列q的队首元素。
  4. q.front():查询q的队首元素。
  5. q.back():查询q的队尾元素。
  6. q.size():查询q的元素个数。
  7. q.empty():查询q是否为空。

priority_queue

优先队列,就是一种容器,默认它的第一个元素即堆顶为最大值。

priority_queue 可以理解为一个大根二叉堆~~(然鹅这东西我也不会)~~。

常用操作

  • q.push(x):把元素插入堆,时间复杂度为 O(log⁡n)O(\log n)O(logn)

  • q.pop():删除堆顶元素(即最大值)

  • int x=q.top:查询堆顶元素(即最大值)

定义

  • 从大到小(大顶堆):priority_queue<int> qpriority_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>

常用操作

  1. set<int> ds:建立一个名字叫做 ds 的、元素类型为 int 的集合。
  2. ds.insert(x):在集合中插入一个元素,如果这个元素已经存在,则什么都不干。
  3. ds.eraase(x):在集合中删除元素 xxx,如果这个元素不存在,则什么都不干。
  4. ds.erase(it):删除集合中地址为 it 的元素。
  5. ds.end():返回集合中最后一个元素的下一个元素的地址。配合其他方法进行比较,以确认某个元素是否存在。
  6. ds.find(x):查询 xxx 在集合中的地址,如果这个数不存在,则返回 ds.end()
  7. ds.lower_bound(x):查询不小于 xxx 的最小的数在集合中的地址,如果这个数不存在,则返回ds.end()
  8. ds.upper_bound(x):查询大于 xxx 的最小的数在集合中的地址,如果这个数不存在,则返回ds.end()
  9. ds.empty():如果集合是空的,则返回 111,否则返回 000
  10. ds.size():返回集合中元素的个数。

multiset

性质

  1. 元素按顺序排列,默认升序
  2. 不去重(与 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(log⁡N)O(\log N)O(logN)

  • insert():最好 O(log⁡N)O(\log N)O(logN),最坏 O(N)O(N)O(N)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值