Logo AND Algorithmique Numérique Distribuée

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