码迷,mamicode.com
首页 > 其他好文 > 详细

优先队列(堆)

时间:2014-11-01 23:24:07      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:style   io   color   os   ar   使用   for   sp   strong   

一、优先队列的一些简单的实现:

    1. 使用一个简单的链表在表头以O(1) 执行插入操作,并遍历该链表以删除最小元,这需要O(N) 的时间。

    2. 始终让表保持有序状态;这使得插入代价高昂(O(N)), 而删除代价低廉(O(1))。基于删除最小元的操作从不多于插入操作的事实,因此,前者是更好地想法。

    3. 使用二叉查找树,它对这两种操作的平均运行时间是O(logN)。尽管插入是随机的,而删除不是,但这个结论还是成立的。由于删除的唯一元素是最小元。反复除去左子树中的节点似乎损害树的平衡,使得右子树加重。然而,右子树是随机的。在最坏的情形,即将左子树删空的情形,右子树拥有的元素最多。(查找树中有许多并不需要的操作)

4. 将要使用的工具二叉堆(堆):它的使用对于优先队列的实现是如此的普遍。

二、 堆具有两个性质:结构性质和堆序性质

1)结构性质:堆是一棵被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入,即为:一棵完全二叉树。

    一棵高为 h 的完全二叉树的节点数为 2^h ~ 2^(h+1)-1。这意味着完全二叉树是O(logN)。

    因为完全二叉树很有规律,所以它可以用一个数组表示,而不使用指针。对数组中任意位置 i 上的元素,其左孩子在 2i 位置处,右孩子在左孩子的后一单元(2i+1)中,它的父节点在 i / 2(下取整) 上。这种实现唯一的问题在于,最大的堆大小需要事先估计,但对于典型的情况这并不成问题。

    因此,一个堆的数据结构将由一个数组(不管关键字是什么类型)、一个代表最大值的整数,以及当前的堆大小组成。

#define MINQUSIZE 5
#define MinData 0.0001
typedef int ElemType;
typedef struct HeapStruct
{
 ElemType *elem;
 int Capasity;
 int Size;
}Heap, *PriorityQueue;

2)堆序性质:使操作被快速执行的性质是堆序性,由于要快速的找出最小元,因此,最小元应该在根上。考虑任意子树也应该是一个堆,那么仁义节点应该小于它的所有后裔。

    在一个堆中,对于每一个节点X, X的父亲中的关键字小于(或等于)X 中的关键字,根节点除外(它没有父亲)。

三、基本操作:

1)插入(Insert):为将一个元素X 插入堆中,我们在下一个空闲位置(数组末尾)创建一个空穴,否则,该堆就不是完全树。如果X 可以放在空穴中,而并不破坏堆的序,那么插入完成。否则,将空穴的父节点上的元素放入空穴中,这样空穴的位置就朝着跟的方向上移一个位置。继续该过程直至 X 能被放入空穴中为止。这一操作称之为上滤

void InsertHeap(ElemType value, PriorityQueue H)
{
int i;
if(H->Size == H->Capasity) //堆已满
  return;
for(i = ++H->Size; H->elem[i / 2] > value; i /= 2)
{
  H->elem[i] = H->elem[i / 2];  //父节点下移
}
H->elem[i] = value;
}

2) 删除操作(DeleteMin):删除最小元。当删除最小元时,在根节点处产生了一个空穴。由于现在堆少了一个元素,因此堆中最后一个元素 X 必须移动到该堆的某个位置。如果 X 可以被放到空穴中,那么删除操作完成。这一般不太可能完成,因此,将空穴的两个儿子中较小的一个移入空穴,这样就把空穴向下推了一层。重复该步骤直到 X 可以被放入空穴中。因此,我们的做法是将 X 置入从根开始包含最小儿子的一条路径上的一个正确位置。

ElemType DeleteMin(PriorityQueue H)
{
int i, child;
ElemType MinElem, LastElem;
if(H->Size == 0)
{
  cout << "PriorityQueue is empty." << endl;
  return H->elem[0];
}

 

//堆的建立
#include<iostream>
#define MINQUSIZE 5
#define MinData 0.0001
using namespace std;
typedef int ElemType;
typedef struct HeapStruct
{
 ElemType *elem;
 int Capasity;
 int Size;
}Heap, *PriorityQueue;
PriorityQueue InitializeHeap(int MaxSize)
{
 PriorityQueue H;
 if (MaxSize < MINQUSIZE)
  throw("Priority queue size is too small.");
 H = new HeapStruct();
 H->elem = new int[MaxSize + 1];
 
 H->Capasity = MaxSize;
 H->Size = 0;
 H->elem[0] = MinData;
 return H;
}
void InsertHeap(ElemType value, PriorityQueue H)
{
 int i;
 if(H->Size == H->Capasity) //堆已满
  return;
 for(i = ++H->Size; H->elem[i / 2] > value; i /= 2)
 {
  H->elem[i] = H->elem[i / 2];  //父节点下移
 }
 H->elem[i] = value;
}
ElemType DeleteMin(PriorityQueue H)
{
 int i, child;
 ElemType MinElem, LastElem;
 if(H->Size == 0)
 {
  cout << "PriorityQueue is empty." << endl;
  return H->elem[0];
 }
 MinElem = H->elem[1];
 LastElem = H->elem[H->Size--];
 for(i = 1; i *2 <= H->Size; i = child)
 {
  child = i * 2; //i 的左孩子
  if(child != H->Size && H->elem[child] > H->elem[child + 1])
   child++;
  if(LastElem > H->elem[child])
   H->elem[i] = H->elem[child]; //空穴下移
  else 
   break;
 }
 H->elem[i] = LastElem;
 return MinElem;
}
int main()
{
 PriorityQueue H;
 H = InitializeHeap(10);
 for(int i = 1; i < 8; i++)
  InsertHeap(i, H);
 for(int j = 0; j <= H->Size; j++)
  cout << H->elem[j] << " ";
 cout << endl;
 DeleteMin(H);
 for(int j = 0; j <= H->Size; j++)
  cout << H->elem[j] << " ";
 system("pause");
 return 0;
}

优先队列(堆)

标签:style   io   color   os   ar   使用   for   sp   strong   

原文地址:http://my.oschina.net/u/2260265/blog/339811

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!