基于堆的优先队列实现
优先队列严格说实际上不是一种队列,因为它并不需要遵循队列的FIFO特性,而要求的基本操作包括:向队列中插入新的记录,以及移出队列中的最大的元素。我们可以以各种不同的方式来实现优先队列——只要能够满足上面的两个接口就可以了。但是基于堆的优先队列则具有较好的性能。
优先队列是一种很有用的数据结构,因为实际上我们不是每时每刻都需要对数据进行严格的排序,有时候我们仅仅能够获得最大的元素的即可,但是如果以顺序查找的方式实现的话,效率上根本满足不了要求。而堆则提供了一种较高效率的实现策略。
网上看到一个面试题(据说是ATC的):写一个在一百万数字中求最大的10个数字的算法。这个问题的解决方案很多,显然考察的是算法的效率(因为基数一百万)。至少有以下几种解法:1)冒泡10次;2)用一个10个大小的数组保存最初10个元素,然后遍历,遇到比最小的大的元素就插入这个数组中,并去掉最小的元素。显然这两种解法的效率都不是特别合适。基于堆的算法应该是提供了一个较好的解决方案,构建大顶堆,取得第一个元素,然后循环10次即可达到题目要求。当然,直接使用基于堆的优先队列可以达到同样的目的。
下面将给出基于堆的优先队列实现,实现源码为:
//Heap.h
#ifndef _HEAP_H_ #define _HEAP_H_
//构建大顶堆 template <class Item> void FixUp(Item* data,int idx) { while (idx > 1) { if (data[idx] > data[idx / 2]) ExchData(data[idx],data[idx / 2]);
idx = idx / 2; } }
template <class Item> void FixDown(Item* data,int len,int idx) { while (idx*2 < len) { int lchild = idx*2;
if ((lchild + 1) == len) { } else { if (data[lchild] < data[lchild + 1]) lchild ++; }
if (data[idx] < data[lchild]) { ExchData(data[idx],data[lchild]); }
idx = lchild; } }
template <class Item> void ExchData(Item& item1,Item& item2) { Item tmp = item1; item1 = item2; item2 = tmp; }
#endif //~_HEAP_H_ |
//PriorityQueue.h
#ifndef _PRIORITYQUEUE_H_ #define _PRIORITYQUEUE_H_
#include "Heap.h"
template <class Item,int LENGTH = 100> class PriorityQueue { public: PriorityQueue() { pq = new Item[LENGTH]; N = 0; }
void Insert(Item item) { if (N >= LENGTH) { //超过了队列长度,插不进去了,懒得处理再分配内存 return ; } pq[++N] = item;
FixUp(pq,N); }
Item getMaxItem() { ExchData(pq[1],pq[N]);
FixDown(pq,N,1);
return pq[N--]; }
private: Item* pq; int N; };
#endif //~_PRIORITYQUEUE_H_ |
测试程序为:
//main.cpp
#include "PriorityQueue.h"
#include <ctime>
#include <iostream> using namespace std;
//data generator,the max Num is MAX_BOUND,1000 default. template <class Item> Item* InitData(int len,int MAX_BOUND = 1000) { Item* data = new Item[len];
srand((unsigned)time(NULL));
for (int i = 0; i < len; i++) { data[i] = rand() % MAX_BOUND; }
return data; }
//print the data template <class Item> void Print(Item* data,int len,char* info) { cout<<info<<endl;
for (int i = 1; i < len;i++) cout<<data[i]<<" ";
cout<<endl; }
int main(int argc,char* argv[]) { const int DATA_LENGTH = 16;
PriorityQueue<int,100> pq;
int* data = InitData<int>(DATA_LENGTH);
Print<int>(data,DATA_LENGTH,"before PriorityQueue sorting");
for (int i = 1; i < DATA_LENGTH; ++i) { pq.Insert(data[i]); }
for (int k = DATA_LENGTH - 1; k > 0; --k) { data[k] = pq.getMaxItem(); }
Print<int>(data,DATA_LENGTH,"after PriorityQueue sorting");
return 0; } |