source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/bheap.cpp @ 2090

Revision 2090, 6.7 KB checked in by gumbau, 17 years ago (diff)
Line 
1/*** Binary Heap Implementation ***/
2/*
3 *   Shane Saunders
4 */
5/* This implementation stores the binary heap in a 1 dimensional array. */
6#include <stdio.h>
7#include <stdlib.h>
8#include "../include/bheap.h"
9
10
11/*** Prototypes for functions internal to the implementation. ***/
12
13void bh_siftup(bheap_t *h, int p, int q);
14
15
16
17/*** Definitions for visible functions. ***/
18
19void bh_dump(bheap_t *h) {
20    int i;
21
22    printf("Heap: \n");
23    for(i = 1; i <= h->n; i++) printf(" %d(%f)\n", h->a[i].item, h->a[i].key);
24    printf("\n");
25   
26    for(i = 2; i <= h->n; i++) {
27        if(h->a[i].key < h->a[i/2].key) {
28            printf("key error at entry %d, value %f\n", i, h->a[i].key);
29            exit(1);
30        }
31    }
32    for(i = 1; i <= h->n; i++) {
33        if(h->p[h->a[i].item] != i) {
34            printf("indexing error at entry %d", i); exit(1);
35        }
36    }   
37}
38
39/* bh_alloc() allocates space for a binary heap of size n and initialises it.
40 * Returns a pointer to the binary heap.
41 */
42bheap_t *bh_alloc(int n)
43{
44    bheap_t *h;
45
46    /* Create the binary heap. */
47    h = (bheap_t *)malloc(sizeof(bheap_t));
48   
49    /* For the purpose of indexing the binary heap, we require n+1 elements in
50     * a[] since the indexing used does not use a[0].
51     */
52    h->a = (bheap_item_t *)calloc(n+1, sizeof(bheap_item_t));
53    h->p = (int *)calloc(n, sizeof(int));
54    h->n = 0;
55    h->key_comps = 0;
56
57    return h;
58}
59
60
61/* bh_free() frees the space taken up by the binary heap pointed to by h.
62 */
63void bh_free(bheap_t *h)
64{
65    free(h->a);
66    free(h->p);
67    free(h);
68}
69
70
71/* bh_min() returns the item with the minimum key in the binary heap pointed to
72 * by h.
73 */
74int bh_min(bheap_t *h)
75{
76    /* The item at the top of the binary heap has the minimum key value. */
77    return h->a[1].item;
78}
79
80
81/* bh_insert() inserts an item and its key value into the binary heap pointed
82 * to by h.
83 */
84void bh_insert(bheap_t *h, int item, double key)
85{
86    /* i - insertion point
87     * j - parent of i
88     * y - parent's entry in the heap.
89     */
90    int i, j;
91    bheap_item_t y;
92
93    /* i initially indexes the new entry at the bottom of the heap. */
94    i = ++(h->n);
95
96    /* Stop if the insertion point reaches the top of the heap. */
97    while(i >= 2) {
98        /* j indexes the parent of i.  y is the parent's entry. */
99        j = i / 2;
100        y = h->a[j];
101
102        /* We have the correct insertion point when the item's key is >= parent
103         * Otherwise we move the parent down and insertion point up.
104         */
105        h->key_comps++;
106        if(key >= y.key) break;
107
108        h->a[i] = y;
109        h->p[y.item] = i;
110        i = j;
111    }
112
113    /* Insert the new item at the insertion point found. */
114    h->a[i].item = item;
115    h->a[i].key = key;
116    h->p[item] = i;
117}
118
119
120/* bh_delete() deletes an item from the binary heap pointed to by h.
121 */
122void bh_delete(bheap_t *h, int item)
123{
124    int n;
125    int p;
126
127    /* Decrease the number of entries in the heap and record the position of
128     * the item to be deleted.
129     */
130    n = --(h->n);
131    p = h->p[item];
132
133    /* Heap needs adjusting if the position of the deleted item was not at the
134     * end of the heap.
135     */
136    if(p <= n) {
137        /* We put the item at the end of the heap in the place of the deleted
138         * item and sift-up or sift-down to relocate it in the correct place in
139         * the heap.
140         */
141        h->key_comps++;
142        if(h->a[p].key <= h->a[n + 1].key) {
143            h->a[p] = h->a[n + 1];
144            h->p[h->a[p].item] = p;
145            bh_siftup(h, p, n);
146        }
147        else {
148            /* Use insert to sift-down, temporarily adjusting the size of the
149             * heap for the call to insert.
150             */
151            h->n = p - 1;
152            bh_insert(h, h->a[n + 1].item, h->a[n+1].key);
153            h->n = n;
154        }
155    }
156}
157/* bh_mark() marks an item from the binary heap pointed to by h.
158 */
159void bh_mark(bheap_t *h, int item, int flag)
160{
161    h->a[h->p[item]].dirty = flag;
162}
163/* bh_get_key() returns the key value of an item from the binary heap h.
164 */
165double bh_get_key(bheap_t *h, int item)
166{
167    return h->a[h->p[item]].key;
168}
169/* bh_is_dirty() returns the dirty value of an item from the binary heap h.
170 */
171int bh_is_dirty(bheap_t *h, int item)
172{
173    return h->a[h->p[item]].dirty;
174}
175
176
177/* bh_decrease_key() decreases the value of 'item's key and then performs
178 * sift-down until 'item' has been relocated to the correct position in the
179 * binary heap.
180 */
181void bh_decrease_key(bheap_t *h, int item, double new_key)
182{
183    int n;
184
185    n = h->n;
186    h->n = h->p[item] - 1;
187
188    bh_insert(h, item, new_key);
189
190    h->n = n;
191}
192
193
194/*** Definitions for internal functions ***/
195
196/* siftup() considers the sub-tree rooted at p that ends at q and moves
197 * the root down, sifting up the minimum child until it is located in the
198 * correct part of the binary heap.
199 */
200void bh_siftup(bheap_t *h, int p, int q)
201{
202    /* y - the heap entry of the root.
203     * j - the current insertion point for the root.
204     * k - the child of the insertion point.
205     * z - heap entry of the child of the insertion point.
206     */
207    int j, k;
208    bheap_item_t y, z;
209
210    /* Get the value of the root and initialise the insertion point and child.
211     */
212    y = h->a[p];
213    j = p;
214    k = 2 * p;
215
216    /* sift-up only if there is a child of the insertion point. */
217    while(k <= q) {
218
219        /* Choose the minimum child unless there is only one. */
220        z = h->a[k];
221        if(k < q) {
222            h->key_comps++;
223            if(z.key > h->a[k + 1].key) z = h->a[++k];
224        }
225
226        /* We stop if the insertion point for the root is in the correct place.
227         * Otherwise the child goes up and the root goes down.  (i.e. swap)
228         */
229        if(y.key <= z.key) break;
230        h->a[j] = z;
231        h->p[z.item] = j;
232        j = k;
233        k = 2 * j;
234    }
235
236    /* Insert the root in the correct place in the heap. */
237    h->a[j] = y;
238    h->p[y.item] = j;
239}
240
241
242
243
244/*** Implement the universal heap structure type ***/
245
246/* Binary heap wrapper functions. */
247
248int _bh_delete_min(void *h) {
249    int v;
250    v = bh_min((bheap_t *)h);
251    bh_delete((bheap_t *)h, v);
252    return v;
253}
254
255void _bh_insert(void *h, int v, double k) {
256    bh_insert((bheap_t *)h, v, k);
257}
258
259void _bh_decrease_key(void *h, int v, double k) {
260    bh_decrease_key((bheap_t *)h, v, k);
261}
262
263int _bh_n(void *h) {
264    return ((bheap_t *)h)->n;
265}
266
267long _bh_key_comps(void *h) {
268    return ((bheap_t *)h)->key_comps;
269}
270
271void *_bh_alloc(int n) {
272    return bh_alloc(n);
273}
274
275void _bh_free(void *h) {
276    bh_free((bheap_t *)h);
277}
278
279void _bh_dump(void *h) {
280    bh_dump((bheap_t *)h);
281}
282
283/* Binary heap info. */
284const heap_info_t BHEAP_info = {
285    _bh_delete_min,
286    _bh_insert,
287    _bh_decrease_key,
288    _bh_n,
289    _bh_key_comps,
290    _bh_alloc,
291    _bh_free,
292    _bh_dump
293};
Note: See TracBrowser for help on using the repository browser.