优先队列严格说实际上不是一种队列,因为它并不需要遵循队列的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;

}

Posted on 2005-08-10 20:25  k_eckel's mindview  阅读(3506)  评论(0编辑  收藏  举报