Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
renamed xbt_(*.[ch]) to \1.
[simgrid.git] / src / xbt / heap.c
1 /* a generic and efficient heap                                             */
2
3 /* Authors: Arnaud Legrand                                                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6    under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "heap_private.h"
9
10 /**
11  * xbt_heap_new:
12  * @init_size: initial size of the heap
13  * @free_func: function to call on each element when you want to free the whole heap (or NULL if nothing to do).
14  *
15  * Creates a new heap.
16  */
17 xbt_heap_t xbt_heap_new(int init_size, void_f_pvoid_t * const free_func)
18 {
19   xbt_heap_t H = calloc(1, sizeof(struct xbt_heap));
20   H->size = init_size;
21   H->count = 0;
22   H->items =
23       (xbt_heapItem_t) calloc(init_size, sizeof(struct xbt_heapItem));
24   H->free = free;
25   return H;
26 }
27
28 /**
29  * xbt_heap_free:
30  * @H: poor victim
31  *
32  * kilkil a heap and its content
33  */
34 void xbt_heap_free(xbt_heap_t H)
35 {
36   int i;
37   if (H->free)
38     for (i = 0; i < H->size; i++)
39       H->free(H->items[i].content);
40   free(H->items);
41   free(H);
42   return;
43 }
44
45 /**
46  * xbt_heap_push:
47  * @H: the heap we're working on
48  * @content: the object you want to add to the heap
49  * @key: the key associated to this object
50  *
51  * Add an element int the heap. The element with the smallest key is
52  * automatically moved at the top of the heap.
53  */
54 void xbt_heap_push(xbt_heap_t H, void *content, xbt_heap_float_t key)
55 {
56   int count = ++(H->count);
57   int size = H->size;
58   xbt_heapItem_t item;
59   if (count > size) {
60     H->size = 2 * size + 1;
61     H->items =
62         (void *) realloc(H->items,
63                          (H->size) * sizeof(struct xbt_heapItem));
64   }
65   item = &(H->items[count - 1]);
66   item->key = key;
67   item->content = content;
68   xbt_heap_increaseKey(H, count - 1);
69   return;
70 }
71
72 /**
73  * xbt_heap_pop:
74  * @H: the heap we're working on
75  *
76  * Extracts from the heap and returns the element with the smallest
77  * key. The element with the next smallest key is automatically moved
78  * at the top of the heap.
79  */
80 void *xbt_heap_pop(xbt_heap_t H)
81 {
82   void *max = CONTENT(H, 0);
83   H->items[0] = H->items[(H->count) - 1];
84   (H->count)--;
85   xbt_heap_maxHeapify(H);
86   if (H->count < H->size / 4 && H->size > 16) {
87     H->size = H->size / 2 + 1;
88     H->items =
89         (void *) realloc(H->items,
90                          (H->size) * sizeof(struct xbt_heapItem));
91   }
92   return max;
93 }
94
95 /**
96  * xbt_heap_maxkey:
97  * @H: the heap we're working on
98  *
99  * Returns the smallest key in the heap without modifying the heap.
100  */
101 xbt_heap_float_t xbt_heap_maxkey(xbt_heap_t H)
102 {
103   return KEY(H, 0);
104 }
105
106 /**
107  * xbt_heap_maxcontent:
108  * @H: the heap we're working on
109  *
110  * Returns the value associated to the smallest key in the heap
111  * without modifying the heap.
112  */
113 void *xbt_heap_maxcontent(xbt_heap_t H)
114 {
115   return CONTENT(H, 0);
116 }
117
118 /**
119  * xbt_heap_maxcontent:
120  * @H: the heap we're working on
121  * 
122  * Restores the heap property once an element has been deleted.
123  */
124 void xbt_heap_maxHeapify(xbt_heap_t H)
125 {
126   int i = 0;
127   while (1) {
128     int greatest = i;
129     int l = LEFT(i);
130     int r = RIGHT(i);
131     int count = H->count;
132     if (l < count && KEY(H, l) < KEY(H, i))
133       greatest = l;
134     if (r < count && KEY(H, r) < KEY(H, greatest))
135       greatest = r;
136     if (greatest != i) {
137       struct xbt_heapItem tmp = H->items[i];
138       H->items[i] = H->items[greatest];
139       H->items[greatest] = tmp;
140       i = greatest;
141     } else
142       return;
143   }
144 }
145
146 /**
147  * xbt_heap_maxcontent:
148  * @H: the heap we're working on
149  * @i: an item position in the heap
150  * 
151  * Moves up an item at position i to its correct position. Works only
152  * when called from xbt_heap_push. Do not use otherwise.
153  */
154 void xbt_heap_increaseKey(xbt_heap_t H, int i)
155 {
156   while (i > 0 && KEY(H, PARENT(i)) > KEY(H, i)) {
157     struct xbt_heapItem tmp = H->items[i];
158     H->items[i] = H->items[PARENT(i)];
159     H->items[PARENT(i)] = tmp;
160     i = PARENT(i);
161   }
162   return;
163 }