在C++中,可以通過std::priority_queue來使用堆。
堆的C語言實現:
heap.c
1 /** @file heap.c 2 * @brief 堆,默認為小根堆,即堆頂為最小. 3 */ 4 #include <stdlib.h> /* for malloc() */ 5 #include <string.h> /* for memcpy() */ 6 typedef int heap_elem_t; // 元素的類型 7 8 /** 9 * @struct 10 * @brief 堆的結構體 11 */ 12 typedef struct heap_t 13 { 14 int size; /** 實際元素個數 */ 15 int capacity; /** 容量,以元素為單位 */ 16 heap_elem_t *elems; /** 堆的數組 */ 17 int (*cmp)(const heap_elem_t*, const heap_elem_t*); 18 }heap_t; 19 20 /** 元素的比較函數 */ 21 /** 基本類型(如 int, long, float, double)的比較函數 */ 22 int cmp_int(const int *x, const int *y) 23 { 24 const int sub = *x - *y; 25 if(sub > 0) 26 { 27 return 1; 28 } 29 else if(sub < 0) 30 { 31 return -1; 32 } 33 else 34 { 35 return 0; 36 } 37 } 38 39 /** 40 * @brief 堆的初始化. 41 * @param[out] h 堆對象的指針 42 * @param[out] capacity 初始容量 43 * @param[in] cmp cmp 比較函數,小於返回-1,等於返回 0 44 * 大於返回 1,反過來則是大根堆 45 * @return 成功返回 0,失敗返回錯誤碼 46 */ 47 int heap_init(heap_t *h, const int capacity, int (*cmp)(const heap_elem_t*, const heap_elem_t*)) 48 { 49 h->size = 0; 50 h->capacity = capacity; 51 h->elems = (heap_elem_t*)malloc(capacity * sizeof(heap_elem_t)); 52 h->cmp = cmp; 53 return 0; 54 } 55 56 /** 57 * @brief 釋放堆. 58 * @param[inout] h 堆對象的指針 59 * @return 成功返回 0,失敗返回錯誤碼 60 */ 61 int heap_uninit(heap_t *h) 62 { 63 h->size = 0; 64 h->capacity = 0; 65 free(h->elems); 66 h->elems = NULL; 67 h->cmp = NULL; 68 return 0; 69 } 70 71 /** 72 * @brief 判斷堆是否為空. 73 * @param[in] h 堆對象的指針 74 * @return 是空,返回 1,否則返回 0 75 */ 76 int heap_empty(const heap_t *h) 77 { 78 return h->size == 0; 79 } 80 81 /** 82 * @brief 獲取元素個數. 83 * @param[in] s 堆對象的指針 84 * @return 元素個數 85 */ 86 int heap_size(const heap_t *h) 87 { 88 return h->size; 89 } 90 91 /* 92 * @brief 小根堆的自上向下篩選算法. 93 * @param[in] h 堆對象的指針 94 * @param[in] start 開始結點 95 * @return 無 96 */ 97 void heap_sift_down(const heap_t *h, const int start) 98 { 99 int i = start; 100 int j; 101 const heap_elem_t tmp = h->elems[start]; 102 for(j = 2 * i + 1; j < h->size; j = 2 * j + 1) 103 { 104 if(j < (h->size - 1) && h->cmp(&(h->elems[j]), &(h->elems[j + 1])) > 0) 105 { 106 j++; /* j 指向兩子女中小者 */ 107 } 108 // tmp <= h->data[j] 109 if(h->cmp(&tmp, &(h->elems[j])) <= 0) 110 { 111 break; 112 } 113 else 114 { 115 h->elems[i] = h->elems[j]; 116 i = j; 117 } 118 } 119 h->elems[i] = tmp; 120 } 121 122 /* 123 * @brief 小根堆的自下向上篩選算法. 124 * @param[in] h 堆對象的指針 125 * @param[in] start 開始結點 126 * @return 無 127 */ 128 void heap_sift_up(const heap_t *h, const int start) 129 { 130 int j = start; 131 int i= (j - 1) / 2; 132 const heap_elem_t tmp = h->elems[start]; 133 134 while(j > 0) 135 { 136 // h->data[i] <= tmp 137 if(h->cmp(&(h->elems[i]), &tmp) <= 0) 138 { 139 break; 140 } 141 else 142 { 143 h->elems[j] = h->elems[i]; 144 j = i; 145 i = (i - 1) / 2; 146 } 147 } 148 h->elems[j] = tmp; 149 } 150 151 /** 152 * @brief 添加一個元素. 153 * @param[in] h 堆對象的指針 154 * @param[in] x 要添加的元素 155 * @return 無 156 */ 157 void heap_push(heap_t *h, const heap_elem_t x) 158 { 159 if(h->size == h->capacity) 160 { 161 /* 已滿,重新分配內存 */ 162 heap_elem_t* tmp = (heap_elem_t*)realloc(h->elems, h->capacity * 2 * sizeof(heap_elem_t)); 163 h->elems = tmp; 164 h->capacity *= 2; 165 } 166 h->elems[h->size] = x; 167 h->size++; 168 heap_sift_up(h, h->size - 1); 169 } 170 171 /** 172 * @brief 彈出堆頂元素. 173 * @param[in] h 堆對象的指針 174 * @return 無 175 */ 176 void heap_pop(heap_t *h) 177 { 178 h->elems[0] = h->elems[h->size - 1]; 179 h->size --; 180 heap_sift_down(h, 0); 181 } 182 183 /** 184 * @brief 獲取堆頂元素. 185 * @param[in] h 堆對象的指針 186 * @return 堆頂元素 187 */ 188 heap_elem_t heap_top(const heap_t *h) 189 { 190 return h->elems[0]; 191 }