ReviewForJob——二叉堆优先队列的实现(三种堆节点类型——int + struct HeapNode + struct HeapNode*)
【0】README
1)本文旨在給出?二叉堆優先隊列的實現 的代碼實現和分析, 而堆節點類型 不外乎三種: 一, 基本類型如int; 二,結構體類型 struct HeapNode; 三,結構體指針類型 struct HeapNode* 類型;
2)為什么要給出 結構體指針類型的 二叉堆實現 ??因為 小生我在 實現 克魯斯卡爾算法 求 最小生成樹的時候,需要用到 二叉堆優先隊列 選取 權值最小的邊,所以要用到 結構體指針類型的 二叉堆實現, 哥子 今天一上午 也 沒有 吧 kruskal alg 實現出來,原因就在于 結構體指針類型 的 二叉堆 沒有 弄清楚;
3)本文末尾對三種堆節點類型的源碼實現 進行了分析和比較;
4)for full source code, please visit?https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6/review
5)wc, 剛才填了一個大坑,你懂的。
// for循環的 leftChild(index) <= size 必須要取 等號.for(temp = data[index]; leftChild(index) <= size; index = child){child = leftChild(index);if(child < size && data[child] < data[child+1]) // if 語句里的 child < size 不取等號.
【1】二叉堆基本操作
操作1)初始化堆;
操作2)基于上濾操作的插入操作;
操作3)基于下濾操作的刪除最小值 (deleteMin);
操作4)decreaseKey 操作;
操作5)increaseKey 操作;
【2】基本類型(int)為堆節點的堆實現
1)堆結構體
// 堆節點類型為 int. #define ElementType intstruct BinaryHeap; typedef struct BinaryHeap *BinaryHeap; struct BinaryHeap {int capacity;int size; ElementType *array; }; 2)源碼實現 // judge whether the BinaryHeap is full or not , also 1 or 0 . // you should know the element under index 0 don't store any content. 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 leftChild(int index) {return index*2; }// initialize binary heap with given capacity. 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->array = temp;bh->array[0] = INT_MIN; // let bh->array[0] be the minimum integer.return bh; }// Attention, the index of the heap starts from 1 // insert the value into binary heap based on percolateUp(). void insert(ElementType value, BinaryHeap bh) { if(isFull(bh)){Error("failed insertion , for the BinaryHeap is full, from func insert!");return ; }bh->array[++bh->size] = value; // startup is 1 not 0.percolateUp(bh->size, bh); }// percolating up the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1 void percolateUp(int i, BinaryHeap bh) { ElementType temp = bh->array[i];for(; temp < bh->array[i/2]; i/=2){bh->array[i] = bh->array[i/2];}bh->array[i] = temp; }// delete minimal from binary heap based on percolateDown(). 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->array; minimum = data[1];swap(&data[1], &data[bh->size]); // &variable means nickname of the variablebh->size-- ; // size-- occurs prior to percolateDown(). percolateDown(1, bh) ; return minimum; } // percolating down the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1void percolateDown(int index, BinaryHeap bh){ ElementType *data;int size;ElementType temp;int child;data = bh->array;size = bh->size;for(temp = data[index]; leftChild(index) < size; index = child){child = leftChild(index);if(child < size && data[child] > data[child+1]){child++;}if(temp > data[child]){data[index] = data[child];}else{break;}}data[index] = temp;}// print binary heap. void printBinaryHeap(BinaryHeap bh) {int i;ElementType *temp;if(!bh){Error("printing execution failure, for binary heap is null, from func printBinaryHeap"); }temp = bh->array;for(i=1; i <= bh->size; i++){printf("\n\t index[%d] = ", i); printf("%d", bh->array[i]); }printf("\n"); } // increase element's value void increaseKey(int index, ElementType increment, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed increaseKey, since overstep the boundary! ");return ;}bh->array[index] += increment; // update the element under given indexpercolateDown(index, bh); }//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->array[index] -= decrement; // update the element under given indexpercolateUp(index, bh); }3)測試用例
int main() {int i;BinaryHeap bh;int capacity;int size;ElementType data[] = {85, 80, 40, 30, 10, 70, 110};capacity = 15;size = 7;bh = initBinaryHeap(capacity);printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap.");for(i = 0; i < size; i++){insert(data[i], bh);} printBinaryHeap(bh);printf("\ninsert {100, 20, 90, 5} into binary heap\n");insert(100, bh);insert(20, bh);insert(90, bh);insert(5, bh);printBinaryHeap(bh);printf("\ndeleteMin from binary heap\n");deleteMin(bh); printBinaryHeap(bh); // other operations in bianry heap printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");increaseKey(2, 85, bh);printBinaryHeap(bh);printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");decreaseKey(9, 85, bh);printBinaryHeap(bh);return 0; }
【3】結構體類型(struct HeapNode)為堆節點的堆實現
1)堆結構體
// 堆節點類型是結構體. struct HeapNode; typedef struct HeapNode* HeapNode; struct HeapNode {int value; };// 二叉堆的結構體. struct BinaryHeap; typedef struct BinaryHeap *BinaryHeap; struct BinaryHeap {int capacity;int size; HeapNode array; // 二叉堆實現為結構體數組. }; // 堆節點類型是 結構體類型 而不是單純的 int類型. #define ElementType struct HeapNode 2)源碼實現 ElementType createElementType(int value) {struct HeapNode node;node.value = value;return node; }// judge whether the BinaryHeap is full or not , also 1 or 0 . // you should know the element under index 0 don't store any content. 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 leftChild(int index) {return index*2; }// initialize binary heap with given capacity. 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->array = temp;bh->array[0].value = INT_MIN; // update: let bh->array[0]->value be the minimum integer.return bh; }// Attention, the index of the heap starts from 1 // insert the value into binary heap based on percolateUp(). void insert(ElementType e, BinaryHeap bh) { if(isFull(bh)){Error("failed insertion , for the BinaryHeap is full.");return ; }bh->array[++bh->size] = e; // startup is 1 not 0.percolateUp(bh->size, bh); }// percolating up the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1 void percolateUp(int i, BinaryHeap bh) { ElementType temp = bh->array[i];for(; temp.value < bh->array[i/2].value; i/=2) // update.{bh->array[i] = bh->array[i/2];}bh->array[i] = temp; }// delete minimal from binary heap based on percolateDown(). ElementType deleteMin(BinaryHeap bh) { ElementType minimum;ElementType *data; data = bh->array; minimum = data[1];swap(&data[1], &data[bh->size]); // &variable means nickname of the variablebh->size-- ; // size-- occurs prior to percolateDown(). percolateDown(1, bh) ; return minimum; } // percolating down the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1void percolateDown(int index, BinaryHeap bh){ ElementType* array; int size;ElementType temp;int child;array = bh->array;size = bh->size;for(temp = array[index]; leftChild(index) <= size; index = child){child = leftChild(index);if(child < size && array[child].value > array[child+1].value){child++;}if(temp.value > array[child].value){array[index] = array[child];}else{break;}}array[index] = temp;}// print binary heap. void printBinaryHeap(BinaryHeap bh) {int i;ElementType *temp;if(!bh){Error("printing execution failure, for binary heap is NULL."); }temp = bh->array;for(i = 1; i <= bh->size; i++){printf("\n\t index[%d] = ", i); printf("%d", bh->array[i]);}printf("\n"); } // increase element's value void increaseKey(int index, int increment, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed increaseKey, since overstep the boundary! ");return ;}bh->array[index].value += increment; // update the element under given indexpercolateDown(index, bh); }//decreasing value of the element under index by increment void decreaseKey(int index, int decrement, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed decreaseKey, since overstep the boundary! ");return ;}bh->array[index].value -= decrement; // update the element under given indexpercolateUp(index, bh); }3)測試用例
// 堆節點是結構體類型. int main() { BinaryHeap bh;int i, capacity, size; int data[] = {85, 80, 40, 30, 10, 70, 110};capacity = 15;size = 7;bh = initBinaryHeap(capacity);printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap with heap node being struct.");for(i = 0; i < size; i++){insert(createElementType(data[i]), bh);} printBinaryHeap(bh);printf("\ninsert {100, 20, 90, 5} into binary heap\n");insert(createElementType(100), bh);insert(createElementType(20), bh);insert(createElementType(90), bh);insert(createElementType(5), bh);printBinaryHeap(bh);printf("\ndeleteMin from binary heap\n");deleteMin(bh); printBinaryHeap(bh); // other operations in bianry heap printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");increaseKey(2, 85, bh);printBinaryHeap(bh);printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");decreaseKey(9, 85, bh);printBinaryHeap(bh);return 0; }
【4】結構體類型指針(struct HeapNode*)為堆節點的堆實現
1)堆結構體
struct HeapNode; typedef struct HeapNode* HeapNode; struct HeapNode {int value; };// 二叉堆的結構體. struct BinaryHeap; typedef struct BinaryHeap *BinaryHeap; struct BinaryHeap {int capacity;int size; HeapNode* array; // 堆節點類型是結構體指針. 而優先隊列是結構體指針數組. }; // 堆節點類型是 結構體指針類型 而不是單純的 int類型. #define ElementType HeapNode2)源碼實現
ElementType createElementType(int value) {HeapNode node = (HeapNode)malloc(sizeof(struct HeapNode));if(node == NULL){Error("failed createElementType() for out of space."); return NULL;}node->value = value;return node; }// judge whether the BinaryHeap is full or not , also 1 or 0 . // you should know the element under index 0 don't store any content. 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) {struct HeapNode temp;temp = *x;*x = *y;*y = temp; }// get the left child of node under index with startup 1 int leftChild(int index) {return index*2; }// initialize binary heap with given capacity. 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->array = temp;// bh->array[0] = INT_MIN; bh->array[0] = (ElementType)malloc(sizeof(struct HeapNode));if(bh->array[0] == NULL){Error("out of space, from func initBinaryHeap"); return NULL;}bh->array[0]->value = INT_MIN; return bh; }// Attention, the index of the heap starts from 1 // insert the value into binary heap based on percolateUp(). void insert(ElementType e, BinaryHeap bh) { if(e == NULL){Error("failed insertion , for e is NULL.");return;}if(isFull(bh)){Error("failed insertion , for the BinaryHeap is full.");return ; }bh->array[++bh->size] = e; // startup is 1 not 0.percolateUp(bh->size, bh); }// percolating up the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1 void percolateUp(int i, BinaryHeap bh) { ElementType temp = bh->array[i];for(; temp->value < bh->array[i/2]->value; i/=2) // update.{bh->array[i] = bh->array[i/2];}bh->array[i] = temp; }// delete minimal from binary heap based on percolateDown(). ElementType deleteMin(BinaryHeap bh) { ElementType minimum;ElementType* array; array = bh->array; minimum = array[1];swap(array[1], array[bh->size]); // &variable means nickname of the variablebh->size-- ; // size-- 在下濾函數執行之前發生.percolateDown(1, bh) ; return minimum; } // percolating down the element when its value is greater than children (minimal heap)//Attention: all of bh->array starts from index 1void percolateDown(int index, BinaryHeap bh){ ElementType* array; int size;ElementType temp;int child;array = bh->array;size = bh->size;for(temp = array[index]; leftChild(index) <= size; index = child){child = leftChild(index);if(child < size && array[child]->value > array[child+1]->value){child++;}if(temp->value > array[child]->value){array[index] = array[child];}else{break;}}array[index] = temp;}// print binary heap. void printBinaryHeap(BinaryHeap bh) {int i;if(!bh){Error("printing execution failure, for binary heap is NULL."); return;}for(i=1; i <= bh->size; i++){printf("\n\t index[%d] = ", i); printf("%d", bh->array[i]->value); }printf("\n"); } // increase element's value void increaseKey(int index, int increment, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed increaseKey, since overstep the boundary! ");return ;}bh->array[index]->value += increment; // update the element under given indexpercolateDown(index, bh); }//decreasing value of the element under index by increment void decreaseKey(int index, int decrement, BinaryHeap bh) { if(index > bh->size || index < 1){Error(" failed decreaseKey, since overstep the boundary! ");return ;}bh->array[index]->value -= decrement; // update the element under given indexpercolateUp(index, bh); }3)測試用例
// 堆節點是結構體指針類型. int main() { BinaryHeap bh;int i, capacity, size; int data[] = {85, 80, 40, 30, 10, 70, 110};capacity = 15;size = 7;bh = initBinaryHeap(capacity);printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap.");for(i = 0; i < size; i++){insert(createElementType(data[i]), bh);} printBinaryHeap(bh);printf("\ninsert {100, 20, 90, 5} into binary heap\n");insert(createElementType(100), bh);insert(createElementType(20), bh);insert(createElementType(90), bh);insert(createElementType(5), bh);printBinaryHeap(bh);printf("\ndeleteMin from binary heap\n");deleteMin(bh); printBinaryHeap(bh); // other operations in bianry heap printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");increaseKey(2, 85, bh);printBinaryHeap(bh);printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");decreaseKey(9, 85, bh);printBinaryHeap(bh);return 0; }
【5】堆節點為 或者int類型 或者結構體類型 或者 結構體指針類型 的源碼分析和總結?
1)注意在以上實現中, 哪些函數是相同的,哪些函數是不同的, 就算有些函數聲明相同,但是函數體是不同的;
2)要知道 堆的第一個存儲空間不用(index == 0):對于int 類型的處理方式是 設置 array[0]=INT_MIN, 對于 struct 類型的處理方式是 array[0].value = INT_MIN,對于 struct* 類型的處理方式是 array[0]->value = INT_MIN,這都是為了 上濾的時候 便于比較;而對于 array[0] 的初始化都是在 初始化堆中的函數完成的;
3)還有一個需要注意的是 swap() 函數:deleteMin() 函數 需要用到 swap()函數,因為 在 刪除最小元元素的時候,是吧 第一個元素 和 最后一個元素進行交換,然后size--,然后再對 index=1 的元素進行下濾操作;所以 swap() 交換函數特別重要;
void swap(ElementType x, ElementType y) // struct HeapNode* 的 swap函數.(堆節點類型是 結構體指針類型) {struct HeapNode temp;temp = *x;*x = *y;*y = temp; } void swap(ElementType *x, ElementType *y) // struct HeapNode 的swap函數.(堆節點類型是 結構體類型) {ElementType temp;temp = *x;*x = *y;*y = temp; } void swap(ElementType *x, ElementType *y) // int 類型的swap函數(堆節點類型是 int基本類型) {ElementType temp;temp = *x;*x = *y;*y = temp; } 4)測試用例中,插入元素進堆,傳入的參數不一樣:雖然 他們的 insert 函數都是?void insert(ElementType value, BinaryHeap bh),對于 int類型來說, ElementType 就是 int, 對于 struct HeapNode 來說,ElementType 就是 struct HeapNode, 而對于 struct HeapNode* 來說, ElementType 就是 ?struct HeapNode*;所以你看到在不同測試用例中,除開 int 基本類型 都是要 創建 堆節點的,然后再傳入; ElementType createElementType(int value) // struct HeapNode 類型的 createElementType() 函數體 {struct HeapNode node;node.value = value;return node; } ElementType createElementType(int value) // struct HeapNode* 類型的 createElemnetType() 函數體. 是很不一樣的,這是我們需要注意的. {HeapNode node = (HeapNode)malloc(sizeof(struct HeapNode));if(node == NULL){Error("failed createElementType() for out of space."); return NULL;}node->value = value;return node; }
總結
以上是生活随笔為你收集整理的ReviewForJob——二叉堆优先队列的实现(三种堆节点类型——int + struct HeapNode + struct HeapNode*)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虎贲中郎将是什么官 虎贲中郎将简单介绍
- 下一篇: 《茶杯头》发布 Xbox 周年纪念更新,