/************************************************ * *author:周翔 *e-mail:[email protected] *blog:http://blog.csdn.net/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大家发现了,请通知声哈