目录
- 💡前言
- 一,优先级队列的使用
- 二,仿函数
- 1,什么是仿函数
- 2,仿函数的简单示例
- 三,优先级队列的底层剖析
💡前言
优先队列(priority_queue)是一种容器适配器,默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。
注意:使用优先级队列要包含头文件 < queue >。
一,优先级队列的使用
代码实现如下:
这里的建堆一般有两种方式:
(1) 一种是一个一个push进vector容器再进行向上调整建堆
(2) 另一种是直接用迭代器区间构造直接建堆(推荐用这种)。
#include <iostream>
#include <queue>
#include <functional>
using namespace std;void test_priority_queue()
{vector<int> v = { 6,0,3,5,4,7,9,1,2,8 };//默认升序//priority_queue<int> pq(v.begin(), v.end());//一个一个尾插建堆priority_queue<int, vector<int>, greater<int>> pq;for (auto e : v){pq.push(e);}//迭代器区间构造,直接建堆//priority_queue<int,vector<int>,greater<int>> pq(v.begin(), v.end());while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;}int main()
{test_priority_queue();return 0;
}
注意:优先级队列默认的大堆,降序排列,如果要升序,就要换仿函数。下图中第三个模板参数就是传仿函数。
使用算法库里的 less 和 greater 算法,需要包含头文件< functional >
二,仿函数
1,什么是仿函数
仿函数也叫函数对象,是一个重载了 operator() 的类,可以使得类的对象像函数一样使用。
2,仿函数的简单示例
operator()并没有参数的个数和返回值,所以使用是十分灵活的。
struct Func1
{//无参无返回值void operator()(){cout << "Func调用" << endl;}
};struct Func2
{//有参无返回值void operator()(int n){while (n--){cout << "Func调用" << endl;}}
};int main()
{Func1 f1;f1(); //使得对象像函数一样使用f1.operator()(); //显示调用cout << endl;Func2 f2;f2(3); //使得对象像函数一样使用return 0;
}
三,优先级队列的底层剖析
namespace ling
{template<class T>class myless{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class mygreater{public:bool operator()(const T& x, const T& y){return x > y;}};template <class T, class Container = vector<T>, class Compare = myless<T>>class priority_queue{public:priority_queue() = default;//迭代器区间构造template <class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){con.push_back(*first);++first;}//建堆for (int i = (con.size() - 1 - 1) / 2; i >= 0; i--){Adjust_down(i);}}bool empty() const{return con.empty();}size_t size() const{return con.size();}// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性const T& top()const{return con[0];}//向上调整void Adjust_up(int child){int parent = (child - 1) / 2;while (child > 0){//if (con[parent] < con[child])if(comp(con[parent], con[child])){swap(con[parent], con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){con.push_back(x);Adjust_up(con.size() - 1);}//向下调整void Adjust_down(int parent){int child = parent * 2 + 1;while (child < con.size()){if (child + 1 < con.size() && comp(con[child], con[child + 1])){child += 1;}//if (con[parent] < con[child])if(comp(con[parent], con[child])){swap(con[parent], con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){swap(con[0], con[con.size() - 1]);con.pop_back();Adjust_down(0);}private:Container con;Compare comp;};
}
测试代码:
void TestQueuePriority()
{ling::priority_queue<int> q1;q1.push(5);q1.push(1);q1.push(4);q1.push(2);q1.push(3);q1.push(6);cout << q1.top() << endl;q1.pop();q1.pop();cout << q1.top() << endl;vector<int> v{ 5,1,4,2,3,6 };ling::priority_queue<int, vector<int>, ling::greater<int>> q2(v.begin(), v.end());cout << q2.top() << endl;q2.pop();q2.pop();cout << q2.top() << endl;
}