STL之queue、priority_queue用法
概述
- STL提供3种容器适配器:stack、queue、priority_queue。容器适配器不是第一类容器,因为它们不提供存放数据的实际数据结构的实现方法。而且容器适配器不支持迭代器。容器适配器的好处:程序员可以选择相应的基础数据结构。
- queue模板类让底层类(默认是deque)展示典型的队列接口。
- queue类的限制比deque更多,不允许随机访问队列元素、不允许遍历队列。而是提供的功能可以从基础数据结构的结尾插入或在开头删除(先进先出FIFO)。priority_queue提供的功能可以按排列顺序插入基础数据结构,并从基础数据结构的前面删除。
- queue能用list和deque实现。priority_queue能用vector和deque实现。默认情况下,queue用deque实现。priority_queue用vector实现。 这两个实现都是其最佳性能。
- 在priority_queue中增加元素时,该元素自动按优先顺序插入,使最高优先级元素(默认是最大值)首先从priority_queue中取出。
通常是用堆排序技术实现的。 这种数据结构成为堆(heap)。默认的元素比较器是less。
优先队列常见用法是是处理堆的有关操作。默认优先队列是大顶堆。 - priority_queue插入与删除
-push操作:根据优先顺序将元素插入相应位置(先调用基础容器的push_back函数,然后用堆排序重新排列元素);
-pop操作:删除最高优先级元素(删除堆顶上的元素后调用基础容器的pop_back函数)。
具体用法
0. 头文件
#include<queue>
1. 声明和初始化
1.1 queue
//声明queue,默认以deque容器实现
queue<int>q1;
//声明queue,以list容器实现
queue<int, list<int>>q1;
//声明一个int类型的queue2,将queue1的元素复制给queue2
queue<int>queue2=queue1;
或 queue<int> queue2(queue1);
1.2 priority_queue
1.2.1 基本数据类型,以int为例
//声明priority_queue,默认以vector容器实现,默认排序是从大到小
priority_queue<int>q11;
//声明priority_queue,以deque容器实现,默认排序是从大到小
priority_queue<int, deque<int>>q11;
//声明priority_queue,设置排序为:从小到大,需要三个参数
//参数内容:存储元素类型、容器类型、顺序定义
priority_queue<int, vector<int>,greater<int>>q11;
1.2.2 结构体
对于结构体而言,排序顺序需要自己实现。
//法一:在结构体里内重载比较函数(使用友元)
struct A{
int x;
int y;
A(int _x, int _y):x(_x),y(_y) {}
friend bool operator < (A a, A b) {
return a.y > b.y; //重载小于号使得小的先出队列
}
};
priority_queue<A> p1; //或priority_queue<A,vector<A>> p1;
//法二:在结构体里内重载比较函数
struct A{
int x;
int y;
A(int _x, int _y):x(_x),y(_y) {}
bool operator < (const A &a) const {
return y > a.y; //重载小于号使得小的先出队列
}
};
priority_queue<A> p1; //或priority_queue<A,vector<A>> p1;
//法三:在结构体外
struct A{
int x;
int y;
A(int _x, int _y):x(_x),y(_y) {}
};
struct cmp {
bool operator ()(const A &a, const A &b) {
return a.y > b.y; //重载使得小的先出队列
}
};
priority_queue<A, vector<A>,cmp> p1; //定义需要3个参数
2. 常用函数(查询)
未特别标注的都是queue、priority_queue通用的函数方法。
2.1 empty()
queue1.empty(); //返回值bool类型,若queue1为空,则返回true
2.2 size()
queue1.size(); //返回值为int类型,queue1当前存放的元素的个数
2.3 front()——queue;
条件是queue不为空
queue1.front(); //返回队列头部元素
2.4 back()——queue
条件是queue不为空
queue1.back(); //返回队列末尾元素
2.5 top()——priority_queue
条件是priority_queue不为空
queue1.top(); //返回队列头部元素
2.6 输出
//设置一个输出函数
void display_queue(queue<int> nums) {
while (!nums.empty()) {
cout << nums.front() << " ";
nums.pop();
}
cout << endl;
}
3. 常用函数(操作)
3.1 push()
//在queue1的队列末尾放入元素2
queue1.push(2)
3.2 emplace()
push()函数和emplace()都是在队列这个容器的末尾插入一个新的元素。
- push() 实际上是调用的底层容器的push_back()函数,新元素的值是push函数参数的一个拷贝。
- emplace() 实际上是调用的底层容器的emplace_back()函数,新元素的值是在容器内部就地构造的,不需要移动或者拷贝。
//在stack1的栈顶放入元素2
stack1.emplace(2);
3.3 pop()
//删除queue1队列头部元素
queue1.pop()
3.4 swap()
//将queue1和queue2交换
queue1.swap(queue2);
4. 实际使用出现的问题和方案
4.1 插入时判断是否已存在相同的元素值?
由于没有find()、count()函数,无法直接调用函数得知队列是否存在相同值。
4.2 将某个值删除(若有重复值)
int key=pq.top();
while(key==pq.top()){
pq.pop();
}