/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.youkuaiyun.com/zhx6044
*
*
*************************************************/
#ifndef PRIORITYQUEUE_HPP
#define PRIORITYQUEUE_HPP
#include <iostream>
template <typename T>
/**
* @brief The PriorityQueue class 使用完全二叉树的顺序实现实现(二叉堆)的优先级队列,这个为最大化堆,大值优先,注释掉的为最小化堆
*/
class PriorityQueue
{
template <typename N>
friend std::ostream& operator << (std::ostream &os, const PriorityQueue<N> &t) {
for (int i = 1;i <= t.nowSize;++i) {
os << t.d[i] << " ";
}
return os;
}
public:
PriorityQueue(int _s = DEFAULT);
PriorityQueue(const T arr[], int n);
~PriorityQueue();
void enQueue(const T &t);
T deQueue();
T head() const;
bool isEmpty() const;
private:
enum {DEFAULT = 20};
int cap;
/**
* @brief nowSize 当前节点的个数,也是完全二叉树最下层最右节点在数组中的下标
*/
int nowSize;
/**
* @brief d 第一个也就是下标为0不存数据,从一开始,这样方便了2*I,2*i+1,和2/i向下取整的计算,也就是左右节点和父节点的计算
*/
T *d;
/**
* @brief expand 扩大空间
*/
void expand();
/**
* @brief build 通过传入的数组建立堆
*/
void build();
/**
* @brief help 辅助函数,实现一个非叶子节点根的子树的向下规格
* @param i
*/
void help(int i);
};
template <typename T>
PriorityQueue<T>::PriorityQueue(int _s):cap(_s),nowSize(0)
{
d = new T[cap];
}
template <typename T>
PriorityQueue<T>::PriorityQueue(const T arr[], int n):cap(n+10),nowSize(n)
{
d = new T[cap];
for (int i = 1;i <= nowSize;++i) {
d[i] = arr[i-1];
}
build();
}
template <typename T>
PriorityQueue<T>::~PriorityQueue()
{
delete[] d;
}
template <typename T>
T PriorityQueue<T>::head() const
{
return d[1];
}
template <typename T>
bool PriorityQueue<T>::isEmpty() const
{
return nowSize == 0;
}
template <typename T>
void PriorityQueue<T>::expand()
{
T *t = d;
d = new T[cap*2];
for (int i = 1;i <= nowSize;++i) {
d[i] = t[i];
}
cap *= cap;
delete[] t;
}
template <typename T>
void PriorityQueue<T>::build()
{
for (int i = nowSize / 2;i > 0;--i) {
help(i);
}
}
template <typename T>
void PriorityQueue<T>::help(int i)
{
T t = d[i];
int c;
while (i * 2 < nowSize) {//存在子节点
c = (d[2 * i] > d[2 * i + 1]) ? (2 * i) : (2 * i + 1);
if (d[c] > t) {
//c = (d[2 * i] < d[2 * i + 1]) ? (2 * i) : (2 * i + 1);
//if (d[c] < t) {
d[i] = d[c];
i = c;
} else {
break;
}
}
d[i] = t;
}
template <typename T>
T PriorityQueue<T>::deQueue()
{
T tem = d[1];
//将最下层最右节点最为新的根,在从新规格一次
d[1] = d[nowSize--];
help(1);//从1开始
return tem;
}
template <typename T>
void PriorityQueue<T>::enQueue(const T &t)
{
if (nowSize == cap - 1) expand();
int i = ++nowSize;
for (;i > 1 && t > d[i/2];i /= 2) {//从这个节点向上比较
// for (;i > 1 && t < d[i/2];i /= 2) {//从这个节点向上比较
d[i] = d[i/2];
}
d[i] = t;
}
#endif // PRIORITYQUEUE_HPP
#include "priorityqueue.hpp"
int main()
{
int arr[] = {40,20,60,15,30,25,10,35,45,50,55};
PriorityQueue<int> pQueue(arr,11);
// pQueue.deQueue();
std::cout << pQueue << std::endl;
}
去掉注释
修护bug一个
template <typename T>
void PriorityQueue<T>::help(int i)
{
T t = d[i];
int c;
//对付最下层最右节点为左节点的问题
if (i * 2 == nowSize) {
if (d[i*2] < t) {
d[i] = d[i*2];
i = 2 * i;
}
}
while (i * 2 < nowSize) {//存在子节点
// c = (d[2 * i] > d[2 * i + 1]) ? (2 * i) : (2 * i + 1);
// if (d[c] > t) {
c = (d[2 * i] < d[2 * i + 1]) ? (2 * i) : (2 * i + 1);
if (d[c] < t) {
d[i] = d[c];
i = c;
} else {
break;
}
}
d[i] = t;
}
测试代码:
#include "priorityqueue.hpp"
int main()
{
int arr[] = {40,20,60,15,50,25,10,35,45,30};
PriorityQueue<int> pQueue(arr,10);
// pQueue.deQueue();
std::cout << pQueue << std::endl;
}
小弟精力有限,bug大家发现了,请通知声哈