admin管理员组文章数量:1624346
目录
一、介绍
二、仿函数
三、priority_queue实现
1.构造
2.插入和删除
3.剩余接口
四、完整代码
一、介绍
priority_queue叫做优先级队列,适配容器是vector。其实就是数据结构中的堆,默认是大堆。若需要小堆,则需要修改模板中的仿函数类型。
template<class T,class Container = vector<T>,class Compare = less<T>>
二、仿函数
仿函数就是operator(),通过重载括号使得对象可以像函数一样通过括号来传递参数调用。
由于堆中的向上/下调整算法需要父子节点的比较,不同的比较方式生成不同的大堆或小堆。于是我们使用模板中传递不同的仿函数结构类型就可以控制优先级队列的大小堆形态。
template<class T>
struct greater
{
bool operator()(const T& a, const T& b)
{
return a > b;
}
};
template<class T>
struct greater
{
bool operator()(const T& a, const T& b)
{
return a < b;
}
};
堆中的向上和向下调整具体算法实现。
void adjust_up(size_t child)
{
Compare com;
int father = (child-1) / 2;
while (child > 0)
{
if (com(_con[father], _con[child]))
{
std::swap(_con[child], _con[father]);
child = father;
father = (child - 1) / 2;
}
else
break;
}
}
void adjust_down(size_t father)
{
Compare com;
size_t child = father * 2 + 1;
while (child < _con.size())
{
if (child+1 < _con.size() && com(_con[child], _con[child+1]))
child++;
if (com(_con[father], _con[child]))
{
std::swap(_con[father], _con[child]);
father = child;
child = father * 2 + 1;
}
else
break;
}
}
三、priority_queue实现
1.构造
无参构造、拷贝构造和析构使用系统默认的就可以满足使用了,不用自己写。
迭代器构造,在将数组建立起来后,从最后一个的非叶子节点开始向下调整,一直到根节点结束,完成一个堆的建立。
priority_queue(){}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
:_con(first, last)
{
for (int i = (_con.size() - 1 - 1)/2; i >= 0; i--)
{
adjust_down(i);
}
}
2.插入和删除
插入时使用适配容器尾插,再对新插入的位置进行向上调整即可。
删除时注意不能先使用适配容器的删除,应该把堆顶的数据和最后一个位置的数据交换,再使用适配容器的尾删,将原堆顶数据弹出。最后从新堆顶开始向下调整一下重新生成堆。如果冒然直接使用适配容器的头删删除堆顶,那么就会导致整个堆的结构被破坏。
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
3.剩余接口
剩余的一些接口就比较简单了,直接使用适配容器的接口即可轻松实现。
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
四、完整代码
#include<vector>
using namespace std;
namespace lwh
{
template<class T>
struct greater
{
bool operator()(const T& a, const T& b)
{
return a > b;
}
};
template<class T>
struct less
{
bool operator()(const T& a, const T& b)
{
return a < b;
}
};
template<class T,class Container = vector<T>,class Compare = less<T>>
class priority_queue
{
private:
void adjust_up(size_t child)
{
Compare com;
int father = (child-1) / 2;
while (child > 0)
{
if (com(_con[father], _con[child]))
{
std::swap(_con[child], _con[father]);
child = father;
father = (child - 1) / 2;
}
else
break;
}
}
void adjust_down(size_t father)
{
Compare com;
size_t child = father * 2 + 1;
while (child < _con.size())
{
if (child+1 < _con.size() && com(_con[child], _con[child+1]))
child++;
if (com(_con[father], _con[child]))
{
std::swap(_con[father], _con[child]);
father = child;
child = father * 2 + 1;
}
else
break;
}
}
public:
priority_queue(){}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
:_con(first, last)
{
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 push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
private:
Container _con;
};
}
本文标签: priorityqueue
版权声明:本文标题:C++ - priority_queue 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728894994a1178296.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论