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; }