priority_queue也叫优先级队列,说是叫队列,实际上是一个堆。
priority_queue的接口:
这些接口可以直接使用vector作为底层来使用:
为什么说priority_queue是堆呢,写一段如下代码:
void priority()
{
priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}cout << endl;
}
main函数调用运行:
发现结果自己按照大堆排序了,它可以排序的原因是因为它的底层是堆,用了堆的向上调整,向下调整。
可以大堆排序就可以小堆排序。priority_queue的模版里可以传三个实例:我们需要再往模版里再传个vector实例,再传个排序实例,升序是great,降序是less:
priority_queue<int,vector<int>,greater<int>> pq;
除了用vector作为实例还可以用deque,因为priority_queue的底层是堆,堆的向上向下调整是用下标进行调整的,deque也有operator[ ]。
课习题215. 数组中的第K个最大元素 - 力扣(LeetCode)
215. 数组中的第K个最大元素 - 力扣(LeetCode)
首先用队列进行一下排序,也就是topk排序,排出最大的前k个:
然后把数组传给我们的pq;
priority_queue有个构造函数可以传区间:
把nums传进来:
第二步:第四步,返回顶部:
测试未通过:
分析:要找第二大的,只需要把第一大的去掉就-行了,所以k只减一次就够了,而不是减几次,所以应该是--k,而不是k--:
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pq(nums.begin(),nums.end());
while(--k)
{
pq.pop();
}
return pq.top();
}
};
模拟实现priority_queue
首先写一下push:
#include<queue>
namespace bitt
{
template<class T,class Containter=vector<T> >
class priority_queue
{
public:
void push(int child);
{
}
private:
Container _con;
};
}
根据我们写堆的经验堆里面进行增删查改是怎么弄的?
例如这样的一个堆:假设我们要在末尾插入一个20:
_con.push_back(x);
那它就不是一个堆了,要想让它还是保持为一个堆需要写一个向上调整函数。
void adjust_queue(int child)
{
int parent = (child - 1 )/ 2;
while (child > 0)
{
if (_con[parent] >_con[ child])
{
swap(_con[parent],_con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
然后是删除值,删除值是先把头尾交换一下:
然后用向下调整法进行调整法 :
然后在写一些size(),empty(),top():
const T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
main函数调用运行:
void test111()
{
bitt::priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
pq.push(5);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
} cout << endl;
}
int main()
{
test111();
}
虽然可以运行正确,但是会报错:因为底层是vector,用的下标访问,下标一旦越界,就会报断言警告。
最后发现是向下调整的问题,改一下:
就可以正常运行不报错了: