priority_queue的底层结构就是堆,因此此处只需对对进行通用的封装即可。
创建一个priority_queue类,这里的Compar是为了增加仿函数。
这个类中会实现堆的push,pop,top,empty,size等接口
首先完成默认构造和使用迭代器构造
这里的迭代器构造在插入后就完成建堆,使用的是向下调整,向下调整的空间复杂度会比向上调整的要简单,减少消耗。
向下调整这里使用的是假设孩子法来确定要交换孩子的下标,交换以后再将父亲和孩子下标更新,进行从上到下的调整,如果比较失效就跳出循环,建堆完成。这里并没有直接使用大于小于,而是使用了一个Compar 类的对象comfunc将参数传进去进行比较,Compar可以以模板的形式传入不同的类型,达到建大堆或者小堆的操作。
这两个就是比较类,重载了()传参数进行比较返回bool值
这里实现了push的操作,需要先将数据进行尾插,然后从尾进行向上调整
向上调整也是和向下调整类似父子的方式进行实现
Pop的实现先将头部数据和尾部数据进行交换,然后再尾删,再进行向下调整,而不是直接进行头删,这样会导致堆的结构被破坏
top,empty,size是直接调用容器中的接口进行实现
完整代码
#pragma once
#include<iostream>
#include<deque>
#include<vector>
using namespace std;
namespace PY
{
template<class T>
struct myless
{
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
struct mylgreater
{
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T,class Container=vector<T>,class Compar=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--)//从最后一个非叶子节点开始调整
{
ajust_down(i);
}
}
void ajust_up(int child)//向上调整
{
Compar comfunc;
int parent = (child - 1) / 2;
while (child > 0)
{
if (comfunc(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
child = parent;
parent= (child - 1) / 2;
}
else
{
break;
}
}
}
void ajust_down(int parent)//向下调整
{
Compar comfunc;
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && comfunc(_con[child], _con[child+1]))
{
++child;
}
if (comfunc(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
ajust_up(_con.size()-1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
ajust_down(0);
}
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
测试代码
// 默认是大堆
void test_priority_queue()
{
vector<int> v = { 3,2,7,6,0,4,1,9,8,5 };
PY::priority_queue<int> q1;
for (auto& e : v)
q1.push(e);
while (!q1.empty())
{
cout << q1.top() << " ";
q1.pop();
}
cout << endl;
}
void test_priority_queue2()
{
vector<int> v = { 1, 5,3,8,7,6};
PY::priority_queue<int> q1(v.begin(),v.end());
while (!q1.empty())
{
cout << q1.top() << " ";
q1.pop();
}
cout << endl;
}
运行结果