程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 堆的C語言實現,C語言實現

堆的C語言實現,C語言實現

編輯:關於C語言

堆的C語言實現,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 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved