优先队列(堆)

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

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

    2. 始终让表保持有序状态;这使得插入代价高昂(O(N)), 而删除代价低廉(O(1))。基于删除最小元的操做从很少于插入操做的事实,所以,前者是更好地想法。数据结构

    3. 使用二叉查找树,它对这两种操做的平均运行时间是O(logN)。尽管插入是随机的,而删除不是,但这个结论仍是成立的。因为删除的惟一元素是最小元。反复除去左子树中的节点彷佛损害树的平衡,使得右子树加剧。然而,右子树是随机的。在最坏的情形,即将左子树删空的情形,右子树拥有的元素最多。(查找树中有许多并不须要的操做)工具

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

2、 堆具备两个性质:结构性质和堆序性质指针

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

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

    由于彻底二叉树颇有规律,因此它能够用一个数组表示,而不使用指针。对数组中任意位置 i 上的元素,其左孩子在 2i 位置处,右孩子在左孩子的后一单元(2i+1)中,它的父节点在 i / 2(下取整) 上。这种实现惟一的问题在于,最大的堆大小须要事先估计,但对于典型的状况这并不成问题。it

    所以,一个堆的数据结构将由一个数组(无论关键字是什么类型)、一个表明最大值的整数,以及当前的堆大小组成。io

#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 中的关键字,根节点除外(它没有父亲)。

3、基本操做:

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;
}
相关文章
相关标签/搜索