堆的C语言实现
在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 }