本文主要参考stl 顺序容器vector(priority_queue),顺序容器List,顺序容器deque(queue, stack)详解_weixin_34128839的博客-CSDN博客
queue,stack是基于deque实现的,都是顺序容器。
deque支持随机访问,queue和stack由于容器特性屏蔽了随机访问(operator [])。
priority_queue是基于vector实现的,底层数据结构是堆。
vector支持随机访问,priority_queue由于容器特性屏蔽了随机访问(operator [])。
一般需要用到最小堆、最大堆时可以用priority_queue来实现。
一般需要用到队列时可以用queue来实现。
一般需要用到栈时可以用stack来实现。
一般需要用到双向队列时可以用deque来实现。
为下一段先介绍一下list。list的本质是一个双向链表,内存空间不连续,通过指针进行操作。
deque是一个double-ended queue,由多个连续内存块构成,deque是list和vector的兼容,分为多个块,每一个块大小是512字节,块通过map块管理,map块里保存每个块得首地址。因此该容器也有索引操作operator[],效率没vector高。另外,deque比vector多了push_front()和pop_front( )操作,在两端进行此操作时与list的效率差不多。
1、构造和赋值
#include<iostream>
//#include<deque> stack和queue库中都包含了deque
#include<stack>
#include<queue> //queue库中包含了priority_queue
#include<string>
using namespace std;
//以下int,string等可替换成其他类型,若类型为struct和class时可能还需考虑操作符重载
//deque的其他构造函数基本和vector一致。
deque<string> dq1(5, "hello"); //创建一个大小为5、值均为"hello"的deque
deque<int> dq2 = { 9,5,2,7 }; //创建一个deque并赋值{9,5,2,7}
//一般只会按如下方式创建,并且除dequeue外只能这么创建
deque<int> dq3;
queue<int> q1; //创建一个空queue。不能加括号,会出问题。
stack<int> st1; //创建一个空stack。不能加括号,会出问题。
priority_queue<int> pr_q1; //创建一个空priority_queue。不能加括号,会出问题。默认大的元素优先级高,即大顶堆/最大堆。
priority_queue<int, vector<int>, less<int>> pr_q2; //这样写,大的元素优先级高。和上一行是等同的定义。
priority_queue<int, vector<int>, greater<int>> pr_q3; //这样写,小的元素优先级高,即小顶堆/最小堆。
//自定义最大堆。
auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) -> bool { return a.second < b.second; };
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pr_que(cmp);
//下标赋值,但不建议这么干,毕竟是把它当队列或栈用的
//dq2[1] = 6; //dq2值为{9,6,2,7}
2、大小
一般不会用到,我们不怎么关注队列和栈的大小,我们只关注它是否为空。
dq2.size() //返回dq2中元素的个数,即dq2的大小,应为4。
dq2.max_size() //返回容器所能容纳的最大元素数目。这是系统或者库所实施的限制,但是容器不一定保证能达到该大小,有可能在还未达到该大小的时候,就已经无法继续分配任何的空间了。这个函数似乎没有什么卵用。
3、进栈、出栈、进队、出队、获得端点值
//dequeue,双向队列
dq3.push_back(2); //队尾进队。队列值为{2}
dq3.push_front(5); //队头进队。队列值为{5,2}
dq3.back(); //返回队尾元素值。应为2
dq3.front(); //返回队头元素值。应为5
dq3.pop_back(); //队尾出队。队列值为{5}
dq3.pop_front(); //队头出队。队列值为{}
//queue,单向队列
q1.push(2); //队尾进队。队列值为{2}
q1.push(5); //队尾进队。队列值为{2,5}
q1.back(); //返回队尾元素。应为5
q1.front(); //返回队头元素。应为2
q1.pop(); //队头出队。队列值为{5}
//stack,栈
st1.push(2); //进栈。栈值为{2}
st1.push(5); //进栈。栈值为{2,5}
st1.top(); //返回栈顶元素值。应为5
st1.pop(); //出栈。栈值为{2}
//priority_queue,优先级队列
//优先级队列默认为最大堆,即以从大到小为优先级顺序,出队的元素为最大的元素。
pr_q1.push(2); //进队。队列值为{2}
pr_q1.push(5); //进队。队列值为{5,2}
pr_q1.push(3); //进队。队列值为{5,3,2}
pr_q1.top(); //返回优先级最大的元素值。应为5
pr_q1.pop(); //出队。队列值为{3,2}
4、判断是否为空
dq2.empty(); //若为空,则返回True,否则返回False。以下几个同理
q1.empty();
st1.empty();
pr_q1.empty();
5、priority_queue的优先级设置
当队列中元素为int、string等可比较的元素时,可直接使用以上成员函数。
当队列中元素为struct,class等元素时,应重载比较函数,比如小于号操作符。具体细节可参考STL 之 priority_queue 的介绍与简单示例_hellokandy的博客-CSDN博客。