文章目录
- priority_queue
- priority_queue 使用
- priority_queue的模拟实现
- 向上调整算法
- 向下调整算法
- push
- pop
- top
- size
- empty
- 仿函数
- 完整代码
priority_queue
优先队列(priority_queue)也是队列的一种,priority_queue的接口是和queue的接口是相同的。所以两者的使用语法也是相同的。我们直接看优先队列(priority——queue)的底层实现原理。
默认情况下priority_queue是大堆。
priority_queue 使用
//用vector作为底层容器,内部构造大堆结构。
priority_queue<int, vector<int>, less<int>> q1;
//用vector作为底层容器,内部构造小堆结构。
priority_queue<int, vector<int>, greater<int>> q2;
//不指定底层容器和内部需要构造的堆结构。
priority_queue<int> q3;
#include <iostream>
#include <functional>
#include <queue>
using namespace std;
int main()
{priority_queue<int> q;q.push(3);q.push(6);q.push(0);q.push(2);q.push(9);q.push(8);q.push(1);while (!q.empty()){cout << q.top() << " ";q.pop();}cout << endl; //9 8 6 3 2 1 0return 0;
}
priority_queue的模拟实现
priority_queue的底层实际上就是堆,模拟实现priority_queue之前,需要知道向下调整和向上调整算法。(下面这两种算法我们均以大堆为例)
向上调整算法
向上调整算法的前提:
若想将其调整为小堆,那么根结点的左右子树必须都为小堆。
若想将其调整为大堆,那么根结点的左右子树必须都为大堆
向堆中插入数据需要使用到向上调整算法
先将元素插入到堆的末尾,即最后一个孩子之后,从插入节点位置开始和父节点比较,(我们以大堆为例),如果目标结点的值比父结点的值大,则交换目标结点与其父结点的位置,并将原目标节点的父节点当作新的目标节点,继续向上调整,调整到根节点结束,此时该树已经是大堆了
图中是以小堆为例:
向下调整算法
向下调整算法的前提:
若想将其调整为小堆,那么根结点的左右子树必须都为小堆。
若想将其调整为大堆,那么根结点的左右子树必须都为大堆
从根节点开始,选出左右孩子值较大的节点,让值较大的节点与父节点的值进行比较,如果值较大的节点比父节点的值小,交换两者位置,将原来值较大的孩子节点作为父节点,继续向下调整,调整到叶子节点结束
图中是以小堆为例:
push
void push(const T & x){_con.push_back(x);AdjustUp(_con.size() - 1);}
pop
void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}
top
const T& top(){return _con[0];}
size
bool size(){return _con.size();}
empty
bool empty(){return _con.empty();}
仿函数
using namespace std;
//仿函数 /函数对象
template <class T>
class Less
{
public:bool operator() (const T& x, const T& y){return x < y;}
};int main()
{Less<int> lessfunc;bool result = lessfunc(6, 2);//仿函数//bool result = lessfunc.operator()(6, 2);cout <<boolalpha <<result << endl;return 0;
}
完整代码
#pragma once
#include<vector>
#include<functional>
using namespace std;//仿函数 /函数对象
template <class T>
class Less
{
public:bool operator() (const T& x, const T& y){return x < y;}
};
template <class T>
class Greater
{
public:bool operator() (const T& x, const T& y){return x > y;}
};namespace cxq
{template<class T, class Container = vector<T>, class Compare = Less<T> >class priority_queue{private:void AdjustDown(int parent)//从根节点开始{Compare com;//仿函数int child = parent * 2 + 1;while (child < _con.size()){//假设默认左孩子大于右孩子// if (child + 1 < _con.size() && _con[child + 1] > _con[child])//右孩子要存在,防止越界if (child + 1 < _con.size() && com(_con[child + 1], _con[child])){child++;}//if (_con[child] > _con[parent])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);int parent = child;child = parent * 2 + 1;}else{break;}}}void AdjustUp(int child){Compare com;//仿函数int parent = (child - 1) / 2;//大堆while (child > 0){//if (_con[child] > _con[parent])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);int child = parent;parent = (child - 1) / 2;}else{break;}}}public://默认构造priority_queue(){}template<class InputIterator>//构造函数priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}//建堆//最后一个非叶子节点for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; i++){AdjustDown(i);}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}const T& top(){return _con[0];}bool empty(){return _con.empty();}bool size(){return _con.size();}private:Container _con;};void test_priority_queue1(){//默认是大堆--less//priority_queue<int> pq;priority_queue<int, vector<int>, Greater<int> > pq;//小堆pq.push(3);pq.push(5);pq.push(1);pq.push(4);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;}class Date{public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream& operator<<(ostream& _cout, const Date& d);//声明private:int _year;int _month;int _day;};ostream& operator<<(ostream& _cout, const Date& d){_cout << d._year << "-" << d._month << "-" << d._day;return _cout;}struct LessPDate{//仿函数bool operator() ( const Date * p1 , const Date* p2){return *p1 < *p2;}};void test_priority_queue2(){//priority_queue<Date> pq;//pq.push(Date(2023, 7, 20));//pq.push(Date(2023, 6, 20));//pq.push(Date(2023, 8, 20));//while (!pq.empty())//{// cout << pq.top() << " ";// pq.pop();//}//cout << endl;priority_queue<Date*, vector<Date*>, LessPDate> pq;pq.push(new Date(2023, 7, 20));pq.push(new Date(2023, 6, 20));pq.push(new Date(2023, 8, 20));while (!pq.empty()){cout << *pq.top() << " ";pq.pop();}cout << endl;}}