堆的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 }

 

你可能感兴趣的:(C语言)