优先级队列的模拟实现
#include<vector>
namespace chy
{
template <class T,class Container = std::vector<T>,class Compare=std::less<T>>
class priority_queue
{
public:
//构造
//建 大堆
//直接使用内置类型的默认构造
priority_queue()
{}
bool empty() const
{
return _con.empty();
}
const T& top()
{
return _con[0];
}
size_t size() const
{
return _con.size();
}
//构造
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
_con.push_back(*first);
first++;
}
//建堆 向下调整
for (int i = (_con.size() - 2) / 2; i >= 0; i--)
{
adjust_down(i);
}
}
//删除 交换 -- 向下调整
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);//交换首尾
_con.pop_back();
adjust_down(0);
}
//向下调整
void adjust_down(int parent)
{
int child = parent * 2 + 1;
while (child<_con.size())
{
if (child + 1 < _con.size() && _con[child] < _con[child + 1])
{
child++;
}
if (_con[parent] < _con[child])
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);//尾插
adjust_up(_con.size()-1);//从当前位置进行调整
}
void adjust_up(int child)
{
int parent = (child - 1) / 2;
while (child>0)
{
if (_con[parent] < _con[child])
{
std::swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
private:
Container _con;
};
}
问题:上述模拟实现的priority_queue是默认生成大堆,大堆与小堆的区别仅是比较时的符号不同。为了方便解决这一问题,模板中的第三个参数就有了作用
仿函数
仿函数本质是就是重载()运算符,相当于在一个类里面把括号重载,每次从该类中定义一个对象,在对象中使用()操作符。
namespace chy
{
template<class T>
class less
{
public:
bool operator()(const T& a,const T& b)
{
return a<b;
}
}
template<class T>
class greater
{
public:
bool operator()(const T& a,const T& b)
{
return a>b;
}
}
}
int main()
{
chy::less<int> No_fun(1,2);
//这里本质上从 less类中定义了一个No_fun对象 该对象使用操作符重载以比较大小
cout<<No_fun(1,2)<<endl;//这里使用的less对象 即只能按照小于比较
chy::greater<int> No_func2(1,2);
//这里本质上从 greater类中定义一个No_fun2对象
cout<<No_fun2(1,2)<<endl;//这里使用的greater对象 即只能按照大于比较
return 0;
}
在priority_queue中以less为默认,用来实现大堆。
仿函数的优缺点
仿函数是模板函数,可以根据不同的类型代表不同的状态。仿函数是模板函数,可以有不同类型,更通用,本质上简化了代码。仿函数是模板函数,其速度比一般函数要慢
仿函数对于优先级队列的优化
std库里面有less和greater的实现
在每次需要比大小的时候都需要创建一个对象。以adjust_up为例。
void adjust_up(size_t child)
{
//创建一个对象 没传的话就是默认less<T>
Compare com;
size_t parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])
if (com(_con[parent], _con[child]))
{
std::swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
使用
int main()
{
int a[]={3,7,8,3,1,2,6,5};
chy::priority_queue<int> qq( a,a+sizeof(a)/sizeof(a[0]) );//用迭代器构造的
chy::priority_queue<int,vector<int>,greater<int> > Qq(a,a+sizeof(a)/sizeof(a[0]));
//用great必须这么写
return 0;
}