pcb 4.1.1
An interactive printed circuit board layout editor.

src/heap.c

Go to the documentation of this file.
00001 
00039 #ifdef HAVE_CONFIG_H
00040 #include "config.h"
00041 #endif
00042 
00043 #include "global.h"
00044 
00045 #include <assert.h>
00046 
00047 #include "heap.h"
00048 
00049 #ifdef HAVE_LIBDMALLOC
00050 #include <dmalloc.h>
00051 #endif
00052 
00053 /* define this for more thorough self-checking of data structures */
00054 #undef SLOW_ASSERTIONS
00055 
00056 /* ---------------------------------------------------------------------------
00057  * some local prototypes
00058  */
00059 
00060 /* ---------------------------------------------------------------------------
00061  * some local types
00062  */
00063 struct heap_element
00064 {
00065   cost_t cost;
00066   void *data;
00067 };
00068 struct heap_struct
00069 {
00070   struct heap_element *element;
00071   int size, max;
00072 };
00073 
00074 /* ---------------------------------------------------------------------------
00075  * some local identifiers
00076  */
00077 static cost_t MIN_COST = 0;
00078 
00079 /* ---------------------------------------------------------------------------
00080  * functions.
00081  */
00082 /* helper functions for assertions */
00083 #ifndef NDEBUG
00084 #ifdef SLOW_ASSERTIONS
00085 static int
00086 __heap_is_good_slow (heap_t * heap)
00087 {
00088   int i;
00089   /* heap condition: key in each node should be smaller than in its children */
00090   /* alternatively (and this is what we check): key in each node should be
00091    * larger than (or equal to) key of its parent. */
00092   /* note that array element[0] is not used (except as a sentinel) */
00093   for (i = 2; i < heap->size; i++)
00094     if (heap->element[i].cost < heap->element[i / 2].cost)
00095       return 0;
00096   return 1;
00097 }
00098 #endif /* SLOW_ASSERTIONS */
00099 static int
00100 __heap_is_good (heap_t * heap)
00101 {
00102   return heap && (heap->max == 0 || heap->element) &&
00103     (heap->max >= 0) && (heap->size >= 0) &&
00104     (heap->max == 0 || heap->size < heap->max) &&
00105 #ifdef SLOW_ASSERTIONS
00106     __heap_is_good_slow (heap) &&
00107 #endif
00108     1;
00109 }
00110 #endif /* ! NDEBUG */
00111 
00115 heap_t *
00116 heap_create ()
00117 {
00118   heap_t *heap;
00119   /* initialize MIN_COST if necessary */
00120   if (MIN_COST == 0)
00121     MIN_COST = -1e23;
00122   assert (MIN_COST < 0);
00123   /* okay, create empty heap */
00124   heap = (heap_t *)calloc (1, sizeof (*heap));
00125   assert (heap);
00126   assert (__heap_is_good (heap));
00127   return heap;
00128 }
00129 
00133 void
00134 heap_destroy (heap_t ** heap)
00135 {
00136   assert (heap && *heap);
00137   assert (__heap_is_good (*heap));
00138   if ((*heap)->element)
00139     free ((*heap)->element);
00140   free (*heap);
00141   *heap = NULL;
00142 }
00143 
00147 void heap_free (heap_t *heap, void (*freefunc) (void *))
00148 {
00149   assert (heap);
00150   assert (__heap_is_good (heap));
00151   for ( ; heap->size; heap->size--)  
00152    {
00153      if (heap->element[heap->size].data)
00154        freefunc (heap->element[heap->size].data);
00155    }
00156 }
00157 
00158 /* -- mutation -- */
00159 
00160 static void
00161 __upheap (heap_t * heap, int k)
00162 {
00163   struct heap_element v;
00164 
00165   assert (heap && heap->size < heap->max);
00166   assert (k <= heap->size);
00167 
00168   heap->element[0].cost = MIN_COST;
00169   for (v = heap->element[k]; heap->element[k / 2].cost > v.cost; k = k / 2)
00170     heap->element[k] = heap->element[k / 2];
00171   heap->element[k] = v;
00172 }
00173 
00174 void
00175 heap_insert (heap_t * heap, cost_t cost, void *data)
00176 {
00177   assert (heap && __heap_is_good (heap));
00178   assert (cost >= MIN_COST);
00179 
00180   /* determine whether we need to grow the heap */
00181   if (heap->size + 1 >= heap->max)
00182     {
00183       heap->max *= 2;
00184       if (heap->max == 0)
00185         heap->max = 256;                /* default initial heap size */
00186       heap->element =
00187         (struct heap_element *)realloc (heap->element, heap->max * sizeof (*heap->element));
00188     }
00189   heap->size++;
00190   assert (heap->size < heap->max);
00191   heap->element[heap->size].cost = cost;
00192   heap->element[heap->size].data = data;
00193   __upheap (heap, heap->size);  /* fix heap condition violation */
00194   assert (__heap_is_good (heap));
00195   return;
00196 }
00197 
00205 static void
00206 __downheap (heap_t * heap, int k)
00207 {
00208   struct heap_element v;
00209 
00210   assert (heap && heap->size < heap->max);
00211   assert (k <= heap->size);
00212 
00213   v = heap->element[k];
00214   while (k <= heap->size / 2)
00215     {
00216       int j = k + k;
00217       if (j < heap->size && heap->element[j].cost > heap->element[j + 1].cost)
00218         j++;
00219       if (v.cost < heap->element[j].cost)
00220         break;
00221       heap->element[k] = heap->element[j];
00222       k = j;
00223     }
00224   heap->element[k] = v;
00225 }
00226 
00230 void *
00231 heap_remove_smallest (heap_t * heap)
00232 {
00233   struct heap_element v;
00234   assert (heap && __heap_is_good (heap));
00235   assert (heap->size > 0);
00236   assert (heap->max > 1);
00237 
00238   v = heap->element[1];
00239   heap->element[1] = heap->element[heap->size--];
00240   if (heap->size > 0)
00241     __downheap (heap, 1);
00242 
00243   assert (__heap_is_good (heap));
00244   return v.data;
00245 }
00246 
00253 void *
00254 heap_replace (heap_t * heap, cost_t cost, void *data)
00255 {
00256   assert (heap && __heap_is_good (heap));
00257 
00258   if (heap_is_empty (heap))
00259     return data;
00260 
00261   assert (heap->size > 0);
00262   assert (heap->max > 1);
00263 
00264   heap->element[0].cost = cost;
00265   heap->element[0].data = data;
00266   __downheap (heap, 0);         /* ooh, tricky! */
00267 
00268   assert (__heap_is_good (heap));
00269   return heap->element[0].data;
00270 }
00271 
00272 /* -- interrogation -- */
00273 
00277 int
00278 heap_is_empty (heap_t * heap)
00279 {
00280   assert (__heap_is_good (heap));
00281   return heap->size == 0;
00282 }
00283 
00284 /* -- size -- */
00285 
00289 int
00290 heap_size (heap_t * heap)
00291 {
00292   assert (__heap_is_good (heap));
00293   return heap->size;
00294 }
00295