优先级队列本质是一个堆,使用vector容器进一步改进进行实现,优先级队列可以传入比较模板参数,来确定建立大根堆还是小根堆, 比较模板参数本质上是一个仿函数。
namespace hhb
{
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return (left < right);
}
};
template<class T>
struct Greater
{
bool operator()(const T& left, const T& right)
{
return (left > right);
}
};
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;
// 找字节点中大的一个
if (child + 1 < _con.size() && _com(_con[child], _con[child + 1]))
{
++child;
}
while (child < _con.size())
{
if (_com(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void AdjustUp(int child)
{
Compare _com;
// 找到父节点
int parent = (child - 1) / 2;
while (child > 0)
{
if (_com(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
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 (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(i);
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
bool empty()
{
return _con.empty();
}
const T& top()
{
return _con.front();
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
}
测试:
#include <iostream>
#include <vector>
using namespace std;
#include "Priority_queue.h"
void test_priority_queue1()
{
hhb::priority_queue<int> pq1;
pq1.push(3);
pq1.push(1);
pq1.push(5);
pq1.push(2);
pq1.push(4);
while (!pq1.empty())
{
cout << pq1.top() << " ";
pq1.pop();
}
cout << endl;
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(4);
v.push_back(3);
v.push_back(5);
hhb::priority_queue<int> pq2(v.begin(), v.end());
while (!pq2.empty())
{
cout << pq2.top() << " ";
pq2.pop();
}
cout << endl;
}
void test_priority_queue2()
{
//Less<int> less;
//cout << less(1, 2) << endl;
hhb::priority_queue<int, vector<int>, hhb::Less<int>> pq1;
pq1.push(1);
pq1.push(2);
pq1.push(3);
pq1.push(4);
pq1.push(5);
while (!pq1.empty())
{
cout << pq1.top() << " ";
pq1.pop();
}
cout << endl;
hhb::priority_queue<int, vector<int>, hhb::Greater<int>> pq2;
pq2.push(5);
pq2.push(4);
pq2.push(3);
pq2.push(2);
pq2.push(1);
while (!pq2.empty())
{
cout << pq2.top() << " ";
pq2.pop();
}
cout << endl;
}
class Date
{
public:
Date(int year = 1949, int month = 10, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
bool operator<(const Date& d) const
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
{
return false;
}
}
bool operator>(const Date& d) const
{
if (_year > d._year)
{
return true;
}
else if (_year == d._year && _month > d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day > d._day)
{
return true;
}
else
{
return false;
}
}
friend ostream& operator<<(ostream& out, const Date& d);
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << '-' << d._month << '-' << d._day;
return out;
}
void test_priority_queue3()
{
hhb::priority_queue<Date, vector<Date>, hhb::Less<Date>> pq1;
pq1.push(Date(2024, 9, 23));
pq1.push(Date(2024, 10, 23));
pq1.push(Date(2024, 8, 23));
while (!pq1.empty())
{
cout << pq1.top() << " ";
pq1.pop();
}
cout << endl;
hhb::priority_queue<Date, vector<Date>, hhb::Greater<Date>> pq2;
pq2.push(Date(2024, 9, 23));
pq2.push(Date(2024, 10, 23));
pq2.push(Date(2024, 8, 23));
while (!pq2.empty())
{
cout << pq2.top() << " ";
pq2.pop();
}
cout << endl;
}
int main()
{
//test_priority_queue1();
//test_priority_queue2();
test_priority_queue3();
return 0;
}