優先隊列(堆)

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;
}
相關文章
相關標籤/搜索