資料結構--6堆(優先佇列)
阿新 • • 發佈:2018-12-01
操作
插入:空穴上濾策略,新元素在堆中上濾直到找出正確位置。
刪除最小者(DeleteMin):返回並刪除佇列中最小的元素,將堆中最後一個元素放入合適位置,空穴下濾策略。
限制:不能進行Find操作。
實現方式
1.利用簡單鏈表,在表頭O(1)插入,遍歷刪除最小元;或者,始終讓連結串列有序,則插入O(N),刪除O(1)。因為插入多於刪除,所以前者更好。
2.利用二叉查詢樹,插入和刪除都是O(logN),利用二叉查詢樹有些大材小用,因為它支援許多不需要的操作。
3.二叉堆,本文所講。
二叉堆性質
- 結構性質
堆是一顆除底層外被完全填滿的二叉樹,底層上的元素從左到右填入,這樣的樹被稱為完全二叉樹。
一顆高為h的完全二叉樹有2^h到2^h-1個節點,即完全二叉樹的高為logN,顯然是O(logN)。
完全二叉樹很有規律,所以可以使用陣列而不需要指標來表示:
對於陣列任一位置i,左二子在2i上,右兒子在(2i + 1)中,父親在i/2上。
一個堆資料結構由一個數組,一個代表最大值的整數,以及當前的堆 - 堆序性質
最小或最大元在根上,可以快速找到。
程式碼:主要是插入和刪除並返回最小元的操作。
#include <iostream> using namespace std; typedef struct HeapStruct { int m_capacity; int m_size; int* m_array; } *PriorityQueue; PriorityQueue Initialize(int capacity); void Destroy(PriorityQueue H); void MakeEmpty(PriorityQueue H); void Insert(PriorityQueue H, int x);//上濾 int DeleteMin(PriorityQueue H); int FindMin(PriorityQueue H); bool IsEmpty(PriorityQueue H); bool IsFull(PriorityQueue H); int main() { } PriorityQueue Initialize(int capacity) { PriorityQueue H = new HeapStruct; if (capacity < 0) cout << "堆容量要大於0" << endl; H->m_array = new int[capacity]; H->m_capacity = capacity; H->m_size = 0; H->m_array[0] = -9999999;//MinData,標誌,相當於哨兵,連結串列中的頭結點 return H; } void Insert(PriorityQueue H, int x) { int i; if (IsFull(H)) { cout << "堆已滿,無法插入" << endl; return; } //空穴位置;父節點>x;上濾。 //此處類似於插入排序,避免交換操作。 //注意H->m_arr[0]為標記,小於堆中的任何元素,用來跳出for迴圈 for (i = ++H->m_size; H->m_array[i / 2] > x; i /= 2) { H->m_array[i] = H->m_array[i / 2];//父下移,移出空位 } H->m_array[i] = x;//填入新元素 } int DeleteMin(PriorityQueue H) { int i, Child; int MinElement = H->m_array[1]; int LastElement = H->m_array[--H->m_size]; if (IsEmpty(H)) { cout << "堆為空,刪除失敗" << endl; return H->m_array[0]; } for (i = 1; i * 2 <= H->m_size; i = Child) { //找到空穴的較小兒子,以便空穴下濾 Child = i * 2; if (Child != H->m_size && H->m_array[Child + 1] < H->m_array[Child]) Child++; //類似於插入排序 if (LastElement > H->m_array[Child])//堆中最後一個元素大於空穴的兒子,移出空位 H->m_array[i] = H->m_array[Child]; else//堆中最後一個元素小於空穴的兒子,停止下濾,跳出迴圈之後,最後一個元素填入空位 break; } H->m_array[i] = LastElement;//入位 return MinElement; }