关于二叉堆(优先队列)的其他操作及其应用
【0】README
0.1)本文總結于 數據結構與算法分析;源代碼均為原創, 旨在了解到我們學習了優先隊列后,還能干些什么東西出來, 增加學習的interest;
0.2)以下列出了 關于二叉堆(優先隊列)的其他有用的操作, 其內容基本可以囊括大部分的優先隊列知識點, 亮點是這里還引入到了 堆排序;
0.3)二叉堆的insert 和 deleteMin 基本操作和概念,參見 http://blog.csdn.net/pacosonswjtu/article/details/49498023
【1】二叉堆的操作應用
1.1)降低關鍵字的值——decreaseKey
- 1)decreaseKey概述: decreaseKey(P, △, H) 操作降低在位置 P處的關鍵字的值, 降值的幅度為正的量△; 由于這可能破壞堆的序, 因此必須通過 上濾 對堆進行調整;
- 2)decreaseKey應用: 該操作對 系統管理程序是有用的, 系統管理程序能夠使它們的程序以最高的優先級來運行;
1.2)增加關鍵字的值——increaseKey
- 1)increaseKey概述: increaseKey(P, △, H) 操作增加在位置 P處的關鍵字的值,增值的幅度為正的量△; 由于這可能破壞堆的序, 因此必須通過 下濾 對堆進行調整;
- 2)increaseKey應用: 許多os 調度程序自動地降低正在過多地消耗 CPU 時間的進程的優先級;
1.3)刪除某個位置上的元素——deleteElement
- 1)deleteElement概述: delete(P, H)操作刪除堆中位置P 上的節點,這通過首先執行 decreaseKey(P, ∞, H), 然后再執行 deleteMin 來完成;
- 2)deleteElement 應用:當一個進程被用戶終止(而不是正常終止時), 它必須從優先隊列中除去;
1.4)構建堆——buildHeap
- 1)buildHeap 概述: buildHeap(H) 操作把N個關鍵字作為輸入并把他們放入空堆中;顯然, 這可以使用 N個相繼的insert操作來完成;
- 2)buildHeap 應用:
1.5)優先隊列的應用(我這里只列出 了選擇問題, 當然遠遠不止這一個應用, 這個應用我還沒有編寫源代碼實現)
- 1)我們將要考察的第一個問題是選擇問題: 當時的輸入是 N 個元素以及一個整數 k, 這N 個元素的集可以是全序的,該選擇問題是要找出 第k個最大的元素;
- 2)利用優先隊列來解決(二叉堆屬于優先隊列): 對上述N個元素建立 大根堆, 然后刪除k-1個最大元素, 那么二叉堆的根節點的元素就是第k個最大元素;
- 3)堆排序: 注意, 如果我們對 k=N 運行該程序并在 元素離開對時記錄他們的值, 那么實際上已經對輸入文件以時間 O(NlogN) 做了排序,這樣就得到一種快速的排序算法——堆排序;
Attention)
- A1) 改動的節點的兒子情況只有3種: 要么一個兒子都沒有, 要么只有一個左兒子,要么有兩個兒子 (不可能只有一個右兒子);
- A2) 就編程而言,上濾的難度 小于 下濾的難度;
其他堆操作的源代碼(核心是 堆的上濾 percolateUp 和下濾percolateDown操作):
【2】source code+printing
2.0)Warning of percolateDown :
- W1)因為涉及到利用下濾操作把隨機數組(下標從0開始)建立堆(buildHeap 操作) , 然而在堆的其他操作,如插入,刪除操作中,使用的下標是從1開始以便于編程;所以我們的下濾操作分為下標從0開始的percolateDownFromZero 和 下標從1開始的percolateDownFromOne,不過上述percolateDown 的兩個版本的 編程idea 都是一樣的,只是數組的起始下標不一樣而已,這是我們應該注意的;
- W2) 代碼中, 只有buildHeap 使用的下濾 percolateDownFromZero 版本,而其他操作使用的是 percolateDownFromOne;
- W3)你要知道實現 堆操作的代碼核心是: 上濾percolateUpFromOne 和下濾操作 percolateDownFromOne + percolateDownFromZero;
2.1)download source code :
https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6
2.2)source code at a glance:
[1st file binaryheap.h]
[2st file binaryHeapBasicOperation.c]
#include "binaryheap.h"//judge whether the BinaryHeap is full or not , also 1 or 0 int isFull(BinaryHeap bh) {return bh->size == bh->capacity - 1 ? 1 : 0 ; }//judge whether the BinaryHeap is empty or not , also 1 or 0 int isEmpty(BinaryHeap bh) {return bh->size == 0 ? 1 : 0 ; }void swap(ElementType *x, ElementType *y) {ElementType temp;temp = *x;*x = *y;*y = temp; }// get the left child of node under index with startup 1 int leftChildFromOne(int index) {return index * 2; }ElementType deleteMin(BinaryHeap bh) { ElementType minimum;ElementType *data; if(isEmpty(bh)){Error("failed deleting minimum , for the BinaryHeap is empty, from func deleteMin !");return -1; }data = bh->elements; minimum = data[1];swap(&data[1], &data[bh->size]);bh->size-- ; // size-- occurs prior to percolateDownFromOne percolateDownFromOne(1, bh) ; return minimum; } // Attention, the index of the heap starts from 1 void insert(ElementType value, BinaryHeap bh) {int i;if(isFull(bh)){Error("failed insertion , for the BinaryHeap is full, from func insert!");return ; }for(i = ++bh->size; bh->elements[i/2] > value; i /= 2)bh->elements[i] = bh->elements[i / 2];bh->elements[i] = value; }BinaryHeap initBinaryHeap(int capacity) {BinaryHeap bh;ElementType *temp;bh = (BinaryHeap)malloc(sizeof(struct BinaryHeap));if(!bh) {Error("out of space, from func initBinaryHeap"); return NULL;} bh->capacity = capacity;bh->size = 0;temp = (ElementType *)malloc(capacity * sizeof(ElementType));if(!temp) {Error("out of space, from func initBinaryHeap"); return NULL;} bh->elements = temp;return bh; }void printBinaryHeap(BinaryHeap bh) {int i;ElementType *temp;if(!bh)Error("printing execution failure, for binary heap is null, from func printBinaryHeap"); temp = bh->elements;for(i = 1; i < bh->capacity; i++){printf("\n\t index[%d] = ", i);if(i <= bh->size)printf("%d", bh->elements[i]);elseprintf("NULL");}printf("\n"); } //print the binary heap who starts from index 0 void printBinaryHeapFromZero(BinaryHeap bh) {int i;ElementType *temp;if(!bh)Error("printing execution failure, for binary heap is null, from func printBinaryHeap"); temp = bh->elements;for(i = 0; i < bh->capacity; i++){printf("\n\t index[%d] = ", i);if(i < bh->size)printf("%d", bh->elements[i]);elseprintf("NULL");}printf("\n"); }[3rd file binaryHeapOtherOperation.c]
#include "binaryheap.h"#define Infinity 10000// switch the elements void swap(ElementType *x, ElementType *y) {ElementType temp;temp = *x;*x = *y;*y = temp; }// get the parent of the element with index int parentFromOne(int index) {return index / 2; }// percolating up the element when its value is greater than children (minimal heap)//Attention: all of bh->elements starts from index 1void percolateUpFromOne(int index, BinaryHeap bh){ ElementType *data;ElementType temp;int size; int parent;data = bh->elements;size = bh->size;for(temp = data[index]; parentFromOne(index) > 0; index = parent){parent = parentFromOne(index);if(parent == 0 || temp > data[parent]) break;else data[index] = data[parent]; }data[index] = temp;}// get the left child of node under index with startup one int leftChildFromOne(int index) {return index * 2; }// percolating down the element when its value is greater than children (minimal heap)//Attention: all of bh->elements starts from index 1void percolateDownFromOne(int index, BinaryHeap bh){ ElementType *data;int size;ElementType temp;int child;data = bh->elements;size = bh->size;for(temp = data[index]; leftChildFromOne(index) <= size; index = child){child = leftChildFromOne(index);if(child < size && data[child] > data[child+1])child++;if(temp > data[child])data[index] = data[child];elsebreak;}data[index] = temp;}//decreasing value of the element under index by increment void decreaseKey(int index, ElementType decrement, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed decreaseKey, since overstep the boundary! ");return ;}bh->elements[index] -= decrement; // update the element under given indexpercolateUpFromOne(index, bh); }//increasing value of the element under index by increment void increaseKey(int index, ElementType increment, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed increaseKey, since overstep the boundary! ");return ;}bh->elements[index] += increment; // update the element under given indexpercolateDownFromOne(index, bh); }//deleting the element under index void deleteElement(int index, BinaryHeap bh) {decreaseKey(index, Infinity, bh); // 1st step, decreaseKey operation placing the element under index upto the root deleteMin(bh); //2nd step, deleteMin deleting the element under the root; } // get the left child of node under index with startup zero int leftChildFromZero(int index) {return index * 2 + 1; }// percolating down the element when its value is greater than children (minimal heap)//Attention: all of bh->elements starts from index 0void percolateDownFromZero(int index, BinaryHeap bh){ ElementType *data;ElementType temp;int size; int child;data = bh->elements;size = bh->size;for(temp = data[index]; leftChildFromZero(index) < size; index = child){child = leftChildFromZero(index);if(child < size - 1 && data[child] > data[child+1])child++;if(temp > data[child])data[index] = data[child];elsebreak;}data[index] = temp; }// building the heap with data in array randomly void buildHeap(BinaryHeap bh) {int i; ElementType *data;data = bh->elements;for(i = bh->size/2; i >= 0; i--)percolateDownFromZero(i, bh); }int main() {ElementType data[] = {85, 80, 40, 30, 10, 70, 110}; // P141 ElementType buildHeapData[] = {150, 80, 40, 30, 10, 70, 110, 100, 20, 90, 60, 50, 120, 140, 130};BinaryHeap bh; int size;int i; int capacity;printf("\n\t=== test for inserting the binary heap with {85, 80, 40, 30, 10, 70, 110} in turn ===\n");capacity = 14;bh = initBinaryHeap(capacity);size = 7; for(i = 0; i < size; i++)insert(data[i], bh);printBinaryHeap(bh);printf("\n\t=== test for inserting the binary heap with {100, 20, 90} in turn ===\n");insert(100, bh);insert(20, bh);insert(90, bh);printBinaryHeap(bh);printf("\n\t=== test for inserting the binary heap with 5 ===\n");insert(5, bh); printBinaryHeap(bh);printf("\n\t=== test for 3 deletings towards the minimum in binary heap ===\n");deleteMin(bh); printBinaryHeap(bh);deleteMin(bh); printBinaryHeap(bh);deleteMin(bh); printBinaryHeap(bh);// other operations in bianry heap printf("\n\t====== test for other operations in bianry heap as follows ======\n");printf("\n\t=== test for increaseKey(4, 120, bh) ===\n");increaseKey(4, 120, bh);printBinaryHeap(bh);printf("\n\t=== test for increaseKey(2, 120, bh) ===\n");increaseKey(2, 120, bh);printBinaryHeap(bh);printf("\n\t=== test for decreaseKey(9, 195, bh) ===\n");decreaseKey(9, 195, bh);printBinaryHeap(bh);printf("\n\t=== test for decreaseKey(4, 90, bh) ===\n");decreaseKey(4, 90, bh);printBinaryHeap(bh);printf("\n\t=== test for decreaseKey(7, 50, bh) ===\n");decreaseKey(7, 50, bh);printBinaryHeap(bh);printf("\n\t=== test for decreaseKey(5, 155, bh) ===\n");decreaseKey(5, 155, bh);printBinaryHeap(bh);printf("\n\t=== test for deleteElement(4, bh) ===\n");deleteElement(4, bh);printBinaryHeap(bh);printf("\n\t=== test for deleteElement(1, bh) ===\n");deleteElement(1, bh);printBinaryHeap(bh);printf("\n\t=== test for deleteElement(3, bh) ===\n");deleteElement(3, bh);printBinaryHeap(bh); // test over , Bingo!// as you know, the build heap operation is identical with other operationsprintf("\n\t=== test for building heap with {150, 80, 40, 30, 10, 70, 110, 100, 20, 90, 60, 50, 120, 140, 130} ===\n");capacity = 16;bh = initBinaryHeap(capacity);bh->size = 15;bh->elements = buildHeapData; buildHeap(bh);printBinaryHeapFromZero(bh);return 0; }2.3)printing results:
總結
以上是生活随笔為你收集整理的关于二叉堆(优先队列)的其他操作及其应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二叉堆(优先队列)
- 下一篇: 包+类导入+静态导入+类放入包中+包作用