用堆实现优先级队列
文章目錄
- 1 用堆實現優先級隊列
1 用堆實現優先級隊列
如果最小鍵值元素擁有最高的優先級,那么這種優先隊列叫作升序優先隊列(即總是先刪除最小的元素),類似的,如果最大鍵值元素擁有最高的優先級,那么這種優先隊列叫作降序優先隊列(即總是先刪除最大的元素);由于這兩種類型是完全對稱的,所以只需要關注其中一種,如升序優先隊列。
算法實現:
#include <stdio.h> #include <stdlib.h> #include <string.h>#define DEFAULT_CAPCITY 128typedef int DataType;#define isLess(a,b) (a<b)typedef struct _PriorityQueue {DataType* arr; //存儲堆元素的數組int size; //當前已存儲的元素個數int capacity; //當前存儲的容量 }PriorityQueue;bool init(PriorityQueue& pq, int* orginal, int size); bool push(PriorityQueue& pq, DataType value); bool pop(PriorityQueue& pq, DataType& value); bool isEmpty(PriorityQueue& pq); bool isFull(PriorityQueue& pq); void destroy(PriorityQueue& pq); static void build(PriorityQueue& pq); static void adjustDown(PriorityQueue& pq, int index); static void adjustUp(PriorityQueue& pq, int index);/*初始化優先隊列*/ bool init(PriorityQueue& pq, DataType* orginal, int size) {int capacity = DEFAULT_CAPCITY > size ? DEFAULT_CAPCITY : size;pq.arr = new DataType[capacity];if (!pq.arr) return false;pq.capacity = capacity;pq.size = 0;//如果存在原始數據則構建最大堆if (size > 0) {//方式一: 直接調整所有元素memcpy(pq.arr, orginal, size * sizeof(int));pq.size = size;//建堆build(pq);}return true; }/*銷毀優先級隊列*/ void destroy(PriorityQueue& pq) {if (pq.arr) delete[] pq.arr; }/*優先隊列是否為空*/ bool isEmpty(PriorityQueue& pq) {if (pq.size < 1) return true;return false; }/*優先隊列是否為滿*/ bool isFull(PriorityQueue& pq) {if (pq.size < pq.capacity) return false;return true; }int size(PriorityQueue& pq) {return pq.size; }/* 從最后一個父節點(size/2-1 的位置)逐個往前調整所有父節點(直到根節 點), 確保每一個父節點都是一個最大堆,最后整體上形成一個最大堆 */ void build(PriorityQueue& pq) {int i;for (i = pq.size / 2 - 1; i >= 0; i--) {adjustDown(pq, i);} }/*將當前的節點和子節點調整成最大堆*/ void adjustDown(PriorityQueue& pq, int index) {DataType cur = pq.arr[index];//當前待調整的節點int parent, child;/*判斷否存在大于當前節點子節點,如果不存在 ,則堆本身是平衡的,不需要調整;如果存在,則將最大的子節點與之交換,交換后,如果這個子節點還有子節點,則要繼續 8979438401111按照同樣的步驟對這個子節點進行調整*/for (parent = index; (parent * 2 + 1) < pq.size; parent = child) {child = parent * 2 + 1;//取兩個子節點中的最大的節點if (((child + 1) < pq.size) && isLess(pq.arr[child], pq.arr[child+ 1])) {child++;}//判斷最大的節點是否大于當前的父節點if (isLess(pq.arr[child], cur)) {//不大于,則不需要調整,跳出循環break;}else {//大于當前的父節點,進行交換,然后從子節點位置繼續向下調整 pq.arr[parent] = pq.arr[child];pq.arr[child] = cur;}} }/*將當前的節點和父節點調整成最大堆*/ void adjustUp(PriorityQueue& pq, int index) {if (index < 0 || index >= pq.size) {//大于堆的最大值直接 returnreturn;}while (index > 0) {DataType temp = pq.arr[index];int parent = (index - 1) / 2;if (parent >= 0) {//如果索引沒有出界就執行想要的操作if (isLess(pq.arr[parent], temp)) {pq.arr[index] = pq.arr[parent];pq.arr[parent] = temp;index = parent;}else {//如果已經比父親小 直接結束循環break;}}else {//越界結束循環break;}} }/* 刪除優先隊列中最大的節點,并獲得節點的值*/ bool pop(PriorityQueue& pq, DataType& value) {if (isEmpty(pq)) return false;value = pq.arr[0];pq.arr[0] = pq.arr[--pq.size];//heap.arr[0] = heap.arr[heap.size-1];//heap.size--;adjustDown(pq, 0);// 向下執行堆調整return true; }/*優先隊列中插入節點*/ bool push(PriorityQueue& pq, DataType value) {if (isFull(pq)) {fprintf(stderr, "優先隊列空間耗盡!\n");return false;}int index = pq.size;pq.arr[pq.size++] = value;adjustUp(pq, index);return true; }int main(void) {PriorityQueue pq;int task[] = { 1, 2, 3, 87, 93, 82, 92, 86, 95 };int i = 0;if (!init(pq, task, sizeof(task) / sizeof(task[0]))) {fprintf(stderr, "初始化優先隊列失敗!\n");exit(-1);}for (i = 0; i < pq.size; i++) {printf("the %dth task:%d\n", i, pq.arr[i]);}//堆中插入優先級為 88 的任務push(pq, 88);//堆中元素出列printf("按照優先級出列:\n");DataType value;while (pop(pq, value)) {printf(" %d\n", value);}destroy(pq);system("pause");return 0; }參考資料:
總結
- 上一篇: 社区团购可以做哪些产品 别只认生鲜产品还
- 下一篇: Qt中的TCP客户端编程