00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "priority_queue.h"
00027 #include "type_limits.h"
00028 #include "debug.h"
00029
00030 #include <stdlib.h>
00031 #include <errno.h>
00032 #include <sys/types.h>
00033
00034
00035
00036
00037
00038 struct element {
00039 void *data;
00040 int key;
00041 size_t *pos;
00042 };
00043
00044 struct priority_queue {
00045 struct element *heap;
00046 size_t capacity;
00047 size_t size;
00048 };
00049
00050
00051 static int upheap(priority_queue_t *pq, size_t n);
00052 static int downheap(priority_queue_t *pq, size_t n);
00053
00054
00055
00056
00057
00058 static inline void place_element(struct element *h, size_t pos,
00059 struct element e)
00060 {
00061 h[pos] = e;
00062 if (h[pos].pos != NULL)
00063 *h[pos].pos = pos;
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static int upheap(priority_queue_t *pq, size_t n)
00075 {
00076 struct element *h = pq->heap;
00077 int i = n;
00078
00079
00080 struct element k = h[n];
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 while (k.key > h[i / 2].key) {
00091 place_element(h, i, h[i / 2]);
00092 i = i / 2;
00093 }
00094
00095
00096 place_element(h, i, k);
00097
00098 return 0;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 static int downheap(priority_queue_t *pq, size_t n)
00110 {
00111 struct element *h = pq->heap;
00112
00113 size_t i = n;
00114
00115
00116 struct element k = h[n];
00117 size_t pq_size = pq->size;
00118
00119
00120
00121 while (2 * i <= pq_size) {
00122 size_t j = 2 * i;
00123
00124
00125
00126
00127
00128 if (j < pq_size && h[j].key < h[j + 1].key) j++;
00129
00130
00131 if (k.key > h[j].key) break;
00132
00133
00134 place_element(h, i, h[j]);
00135
00136
00137 i = j;
00138 }
00139
00140
00141 place_element(h, i, k);
00142
00143 return 0;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 int priority_queue_new(priority_queue_t **pq, size_t capacity)
00159 {
00160 if (pq == NULL)
00161 return_error(EINVAL);
00162
00163 priority_queue_t *p = malloc(sizeof *p);
00164
00165 if (p == NULL)
00166 return_error(ENOMEM);
00167
00168
00169
00170
00171
00172
00173 p->heap = malloc((capacity + 1) * sizeof *p->heap);
00174
00175 if (p->heap == NULL) {
00176 free(p);
00177 return_error(ENOMEM);
00178 }
00179
00180 p->capacity = capacity;
00181 p->size = 0;
00182
00183
00184 p->heap[0].key = __MAX(int);
00185 p->heap[0].data = NULL;
00186
00187 *pq = p;
00188
00189 return 0;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 int priority_queue_free(priority_queue_t *pq)
00203 {
00204 if (pq == NULL)
00205 return_error(EINVAL);
00206
00207 free(pq->heap);
00208 free(pq);
00209
00210 return 0;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 int priority_queue_get_size(priority_queue_t *pq, size_t *size)
00223 {
00224 if (pq == NULL || size == NULL)
00225 return_error(EINVAL);
00226
00227 *size = pq->size;
00228
00229 return 0;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 int priority_queue_add(priority_queue_t *pq, void *data, int key, size_t *pos)
00243 {
00244 if (pq == NULL)
00245 return_error(EINVAL);
00246
00247
00248 if (pq->size >= pq->capacity) {
00249
00250 size_t new_size = ((5 * pq->capacity) / 4) + 1;
00251 struct element *t = realloc(pq->heap, (new_size + 1) * sizeof *t);
00252 if (t == NULL)
00253 return_error(ENOMEM);
00254
00255 pq->heap = t;
00256 pq->capacity = new_size;
00257 }
00258
00259
00260 pq->heap[++pq->size].data = data;
00261 pq->heap[pq->size].key = key;
00262 pq->heap[pq->size].pos = pos;
00263
00264
00265 upheap(pq, pq->size);
00266
00267 return 0;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 int priority_queue_remove_max(priority_queue_t *pq, void **data)
00280 {
00281 if (pq == NULL || data == NULL)
00282 return_error(EINVAL);
00283
00284
00285 struct element k = pq->heap[1];
00286
00287
00288 place_element(pq->heap, 1, pq->heap[pq->size]);
00289
00290 pq->size--;
00291
00292
00293 downheap(pq, 1);
00294
00295 *data = k.data;
00296
00297 return 0;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 int priority_queue_change_key(priority_queue_t *pq, size_t pos, int key)
00310 {
00311 if (pq == NULL || pos > pq->size)
00312 return_error(EINVAL);
00313
00314 struct element *e = &pq->heap[pos];
00315 int old_key = e->key;
00316
00317 e->key = key;
00318
00319 if (key < old_key)
00320 downheap(pq, pos);
00321 else if (key > old_key)
00322 upheap(pq, pos);
00323
00324 return 0;
00325 }