00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "defs.h"
00050 #include "errors.h"
00051 #include "mempool.h"
00052 #include "priority_queue.h"
00053
00058 #define PRQ_comparison_fn(x) ((x)->comparison_fn)
00059 #define PRQ_mem_pool(x) ((x)->mem_pool)
00060 #define PRQ_size(x) ((x)->size)
00061 #define PRQ_allocated_size(x) ((x)->allocated_size)
00062 #define PRQ_expansion_factor(x) ((x)->expansion_factor)
00063 #define PRQ_get_index_fn(x) ((x)->get_index_fn)
00064 #define PRQ_set_index_fn(x) ((x)->set_index_fn)
00065 #define PRQ_heap_vector(x) ((x)->heap_vector)
00066
00067
00073
00074
00075
00076
00077
00078
00079
00080
00081 void*
00082 PRQ_Ith(
00083 PRQ* prq,
00084 INT32 i
00085 )
00086 {
00087 return PRQ_heap_vector(prq)[i-1];
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 extern INT32
00099 PRQ_Size(
00100 PRQ* prq
00101 )
00102 {
00103 return PRQ_size(prq);
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 static void
00115 PRQ_Set_Ith(
00116 PRQ* prq,
00117 INT32 i,
00118 void* element
00119 )
00120 {
00121 if ( PRQ_set_index_fn(prq) != NULL ) {
00122 PRQ_set_index_fn(prq)(element,i);
00123 }
00124
00125 PRQ_heap_vector(prq)[i-1] = element;
00126 }
00127
00128
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 static INT32
00150 PRQ_Upheap(
00151 PRQ* prq,
00152 INT32 index
00153 )
00154 {
00155 void* element;
00156
00157 FmtAssert(index <= PRQ_size(prq) && index > 0,
00158 ("PRQ_Upheap: index %d out of bounds %d",
00159 index,PRQ_size(prq)));
00160
00161 element = PRQ_Ith(prq,index);
00162
00163
00164
00165
00166
00167 while ( index > 1 ) {
00168 INT32 parent_index = index / 2;
00169 void* parent = PRQ_Ith(prq,parent_index);
00170
00171 if ( ! PRQ_comparison_fn(prq)(element,parent) )
00172 break;
00173
00174 PRQ_Set_Ith(prq,index,parent);
00175 index = parent_index;
00176 }
00177
00178 PRQ_Set_Ith(prq,index,element);
00179
00180 return index;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 static INT32
00196 PRQ_Downheap(
00197 PRQ* prq,
00198 INT32 index
00199 )
00200 {
00201 void* element;
00202
00203 FmtAssert(index <= PRQ_size(prq) && index > 0,
00204 ("PRQ_down: index %d out of bounds %d",
00205 index,PRQ_size(prq)));
00206
00207 element = PRQ_Ith(prq,index);
00208
00209
00210
00211
00212
00213
00214 for(;;) {
00215 void* left_child;
00216 INT32 left_child_index = index * 2;
00217 INT32 right_child_index = left_child_index + 1;
00218
00219 if ( left_child_index > PRQ_size(prq) ) break;
00220
00221 left_child = PRQ_Ith(prq,left_child_index);
00222
00223
00224
00225
00226
00227
00228 if ( right_child_index <= PRQ_size(prq)
00229 && PRQ_comparison_fn(prq)(PRQ_Ith(prq,right_child_index),
00230 left_child)
00231 ) {
00232 void* right_child = PRQ_Ith(prq,right_child_index);
00233
00234 if ( PRQ_comparison_fn(prq)(right_child,element) ) {
00235 PRQ_Set_Ith(prq,index,right_child);
00236 index = right_child_index;
00237 }
00238 else
00239 break;
00240 }
00241 else if ( PRQ_comparison_fn(prq)(left_child,element) ) {
00242
00243 PRQ_Set_Ith(prq,index,left_child);
00244 index = left_child_index;
00245 }
00246 else
00247 break;
00248 }
00249
00250 PRQ_Set_Ith(prq,index,element);
00251
00252 return index;
00253 }
00254
00255
00262
00263
00264
00265
00266
00267
00268
00269
00270 void
00271 PRQ_Initialize(
00272 PRQ* prq,
00273 PRQ_COMPARISON_FUNCTION comparison_fn,
00274 PRQ_GET_INDEX_FUNCTION get_fn,
00275 PRQ_SET_INDEX_FUNCTION set_fn,
00276 MEM_POOL* pool,
00277 INT32 initial_size,
00278 INT32 expansion_factor
00279 )
00280 {
00281 if ( initial_size <= 0 ) {
00282 DevWarn("Non positive priority queue initial size %d. Using 200",
00283 initial_size);
00284 initial_size = 200;
00285 }
00286
00287 if ( expansion_factor <= 100 ) {
00288 DevWarn("Priority queue expansion factor should be at least 100. "
00289 "Was %d using 200",expansion_factor);
00290 expansion_factor = 200;
00291 }
00292
00293 PRQ_comparison_fn(prq) = comparison_fn;
00294 PRQ_get_index_fn(prq) = get_fn;
00295 PRQ_set_index_fn(prq) = set_fn;
00296 PRQ_mem_pool(prq) = pool;
00297 PRQ_size(prq) = 0;
00298 PRQ_allocated_size(prq) = initial_size;
00299 PRQ_expansion_factor(prq) = expansion_factor;
00300 PRQ_heap_vector(prq) = TYPE_MEM_POOL_ALLOC_N(void*,pool,initial_size);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 void*
00313 PRQ_Delete_Top( PRQ* prq )
00314 {
00315 void* top_element;
00316
00317 FmtAssert(PRQ_size(prq) > 0,("Deleting from empty heap"));
00318
00319 top_element = PRQ_Ith(prq,1);
00320 if ( PRQ_size(prq) == 1 )
00321 PRQ_size(prq) = 0;
00322 else {
00323
00324
00325
00326 void* bottom_element = PRQ_Ith(prq,PRQ_size(prq));
00327
00328 --PRQ_size(prq);
00329 PRQ_Set_Ith(prq,1,bottom_element);
00330 (void) PRQ_Downheap(prq,1);
00331 }
00332
00333 return top_element;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 void*
00347 PRQ_Top( PRQ* prq )
00348 {
00349 FmtAssert(PRQ_size(prq) > 0,("Topping empty queue"));
00350
00351 return PRQ_Ith(prq,1);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void
00364 PRQ_Insert(
00365 PRQ* prq,
00366 void* element
00367 )
00368 {
00369
00370
00371 if ( PRQ_size(prq) == PRQ_allocated_size(prq) ) {
00372 INT32 new_size = (PRQ_size(prq) * PRQ_expansion_factor(prq)) / 100;
00373
00374 if ( new_size <= PRQ_size(prq) ) {
00375 DevWarn("Priority queue expansion failed -- forcing expansion by 10");
00376 new_size = PRQ_size(prq) + 10;
00377 }
00378
00379 PRQ_heap_vector(prq) =
00380 TYPE_MEM_POOL_REALLOC_N(void*,PRQ_mem_pool(prq),PRQ_heap_vector(prq),
00381 PRQ_allocated_size(prq),
00382 new_size);
00383 PRQ_allocated_size(prq) = new_size;
00384 }
00385
00386
00387
00388
00389 ++PRQ_size(prq);
00390 PRQ_Set_Ith(prq,PRQ_size(prq),element);
00391 (void) PRQ_Upheap(prq,PRQ_size(prq));
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 void
00404 PRQ_Remove(
00405 PRQ* prq,
00406 void* element
00407 )
00408 {
00409 INT32 index = UNDEFINED;
00410
00411 FmtAssert(PRQ_size(prq) > 0,("PRQ_RemoveElement -- empty queue"));
00412
00413
00414
00415
00416
00417
00418 if ( PRQ_get_index_fn(prq) ) {
00419 index = PRQ_get_index_fn(prq)(element);
00420 FmtAssert(element == PRQ_Ith(prq,index),
00421 ("Invalid priority queue index %d",index));
00422 }
00423 else {
00424 INT32 i;
00425
00426 for ( i = 1; i <= PRQ_size(prq); ++i ) {
00427 if ( PRQ_Ith(prq,i) == element ) {
00428 index = i;
00429 break;
00430 }
00431 }
00432 }
00433
00434 FmtAssert(index != UNDEFINED,("Remove a PRQ element not in queue"));
00435
00436
00437
00438
00439 if ( index == PRQ_size(prq) )
00440 --PRQ_size(prq);
00441 else {
00442
00443
00444
00445
00446 void* bottom_element = PRQ_Ith(prq,PRQ_size(prq));
00447
00448
00449
00450 --PRQ_size(prq);
00451 PRQ_Set_Ith(prq,index,bottom_element);
00452
00453
00454
00455
00456 if ( index == PRQ_Upheap(prq,index) )
00457 (void) PRQ_Downheap(prq,index);
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 void
00471 PRQ_Reset( PRQ* prq )
00472 {
00473 PRQ_size(prq) = 0;
00474 }