堆的原理及实现
文章目錄
- 1 堆的原理
- 2 堆的實現
- 2.1 堆的創建
- 2.2 向堆中插入新元素
- 2.3 堆頂元素出堆
1 堆的原理
先看一下堆長什么樣:
最大堆的特點:
看一下如下幾個符不符合最大堆的定義:
(A、B不是,C是最大堆。)
看一下堆的特點:
- 堆是你見過的最有個性的樹!它是用數組表示的樹!
對于i子結點:
- i的左子結點為:2 * i + 1
- i的右子結點為:2 * i + 2
- i的父結點:(i - 1) / 2
2 堆的實現
2.1 堆的創建
在數組中快速創建堆:
算法實現如下:
堆數據結構的定義:
#define DEFAULT_CAPCITY 128typedef struct _Heap{int *arr; //存儲堆元素的數組int size; //當前已存儲的元素個數int capacity; //當前存儲的容量 }Heap;建最大堆:
bool initHeap(Heap &heap, int *orginal, int size); static void buildHeap(Heap &heap); static void adjustDown(Heap &heap, int index);/*初始化堆*/ bool initHeap(Heap &heap, int *orginal, int size){int capacity = DEFAULT_CAPCITY>size? DEFAULT_CAPCITY:size;heap.arr = new int[capacity];if(!heap.arr) return false;heap.capacity = capacity;heap.size = 0;//如果存在原始數據則構建堆if(size>0){memcpy(heap.arr, orginal, size*sizeof(int));heap.size = size;buildHeap(heap);}else {heap.size = 0;}return true; }/*將當前的節點和子節點調整成最大堆*/ void adjustDown(Heap &heap, int index) { int cur=heap.arr[index];//當前待調整的節點int parent,child;/*判斷否存在大于當前節點子節點,如果不存在 ,則堆本身是平衡的,不需要調整;如果存在,則將最大的子節點與之交換,交換后,如果這個子節點還有子節點,則要繼續按照同樣的步驟對這個子節點進行調整*/for(parent=index; (parent*2+1)<heap.size; parent=child){child=parent*2+1;//取兩個子節點中的最大的節點if(((child+1)<heap.size)&&(heap.arr[child]<heap.arr[child+1])){child++;}//判斷最大的節點是否大于當前的父節點if(cur>=heap.arr[child]){//不大于,則不需要調整,跳出循環break;}else {//大于當前的父節點,進行交換,然后從子節點位置繼續向下調整heap.arr[parent]=heap.arr[child];heap.arr[child]=cur;}} }/* 從最后一個父節點(size/2-1 的位置)逐個往前調整所有父節點 (直到根節點),確保每一個父節點都是一個最大堆,最后整體上形成一個最大堆 */ void buildHeap(Heap &heap){int i;for(i=heap.size/2-1; i>=0; i--){adjustDown(heap, i);} }2.2 向堆中插入新元素
代碼實現:
這樣的話我們就可以有另一種創建堆的方式:
/*初始化堆*/ bool initHeap(Heap &heap, int *orginal, int size) {int capacity = DEFAULT_CAPCITY>size ? DEFAULT_CAPCITY : size;heap.arr = new int[capacity];if (!heap.arr) return false;heap.capacity = capacity;heap.size = 0;//如果存在原始數據則構建堆if(size > 0){/*方式一: 直接調整所有元素memcpy(heap.arr, orginal, size*sizeof(int));heap.size = size;//建堆buildHeap(heap);*///方式二: 一次插入一個for(int i=0; i<size; i++){insert(heap, orginal[i]);}}return true; }2.3 堆頂元素出堆
如果我們將堆頂的元素刪除,那么頂部有一個空的節點,怎么處理?
當插入節點的時候,我們將新的值插入數組的尾部?,F在我們來做相反的事情:我們取出數組中的最后一個元素,將它放到堆的頂部,然后再修復堆屬性。
/* 刪除優先隊列中最大的節點,并獲得節點的值*/ bool pop(Heap& heap, int &value) {if (!heap || (heap->size==0)) return false;value = heap.arr[0];pq.arr[0] = heap.arr[--heap.size];//heap.arr[0] = heap.arr[heap.size-1];//heap.size--;adjustDown(heap, 0);// 向下執行堆調整return true; }參考資料:
總結
- 上一篇: 请求模式解决共享资源冲突
- 下一篇: Qt中线程的生命期问题