pcb 4.1.1
An interactive printed circuit board layout editor.
|
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