00001
00002
00005 #include "stdafx.h"
00006 #include "queue.h"
00007 #include "core/alloc_func.hpp"
00008
00009
00010
00011
00012
00013
00014 static void InsSort_Clear(Queue *q, bool free_values)
00015 {
00016 InsSortNode *node = q->data.inssort.first;
00017 InsSortNode *prev;
00018
00019 while (node != NULL) {
00020 if (free_values) free(node->item);
00021 prev = node;
00022 node = node->next;
00023 free(prev);
00024 }
00025 q->data.inssort.first = NULL;
00026 }
00027
00028 static void InsSort_Free(Queue *q, bool free_values)
00029 {
00030 q->clear(q, free_values);
00031 }
00032
00033 static bool InsSort_Push(Queue *q, void *item, int priority)
00034 {
00035 InsSortNode *newnode = MallocT<InsSortNode>(1);
00036
00037 newnode->item = item;
00038 newnode->priority = priority;
00039 if (q->data.inssort.first == NULL ||
00040 q->data.inssort.first->priority >= priority) {
00041 newnode->next = q->data.inssort.first;
00042 q->data.inssort.first = newnode;
00043 } else {
00044 InsSortNode *node = q->data.inssort.first;
00045 while (node != NULL) {
00046 if (node->next == NULL || node->next->priority >= priority) {
00047 newnode->next = node->next;
00048 node->next = newnode;
00049 break;
00050 }
00051 node = node->next;
00052 }
00053 }
00054 return true;
00055 }
00056
00057 static void *InsSort_Pop(Queue *q)
00058 {
00059 InsSortNode *node = q->data.inssort.first;
00060 void *result;
00061
00062 if (node == NULL) return NULL;
00063 result = node->item;
00064 q->data.inssort.first = q->data.inssort.first->next;
00065 assert(q->data.inssort.first == NULL || q->data.inssort.first->priority >= node->priority);
00066 free(node);
00067 return result;
00068 }
00069
00070 static bool InsSort_Delete(Queue *q, void *item, int priority)
00071 {
00072 return false;
00073 }
00074
00075 void init_InsSort(Queue *q)
00076 {
00077 q->push = InsSort_Push;
00078 q->pop = InsSort_Pop;
00079 q->del = InsSort_Delete;
00080 q->clear = InsSort_Clear;
00081 q->free = InsSort_Free;
00082 q->data.inssort.first = NULL;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS)
00092 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1)
00093
00094
00095
00096
00097
00098 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK]
00099
00100 static void BinaryHeap_Clear(Queue *q, bool free_values)
00101 {
00102
00103 uint i;
00104 uint j;
00105
00106 for (i = 0; i < q->data.binaryheap.blocks; i++) {
00107 if (q->data.binaryheap.elements[i] == NULL) {
00108
00109 break;
00110 }
00111
00112 if (free_values) {
00113 for (j = 0; j < (1 << BINARY_HEAP_BLOCKSIZE_BITS); j++) {
00114
00115 if ((q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS) == i &&
00116 (q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
00117 break;
00118 }
00119 free(q->data.binaryheap.elements[i][j].item);
00120 }
00121 }
00122 if (i != 0) {
00123
00124 free(q->data.binaryheap.elements[i]);
00125 q->data.binaryheap.elements[i] = NULL;
00126 }
00127 }
00128 q->data.binaryheap.size = 0;
00129 q->data.binaryheap.blocks = 1;
00130 }
00131
00132 static void BinaryHeap_Free(Queue *q, bool free_values)
00133 {
00134 uint i;
00135
00136 q->clear(q, free_values);
00137 for (i = 0; i < q->data.binaryheap.blocks; i++) {
00138 if (q->data.binaryheap.elements[i] == NULL) break;
00139 free(q->data.binaryheap.elements[i]);
00140 }
00141 free(q->data.binaryheap.elements);
00142 }
00143
00144 static bool BinaryHeap_Push(Queue *q, void *item, int priority)
00145 {
00146 #ifdef QUEUE_DEBUG
00147 printf("[BinaryHeap] Pushing an element. There are %d elements left\n", q->data.binaryheap.size);
00148 #endif
00149
00150 if (q->data.binaryheap.size == q->data.binaryheap.max_size) return false;
00151 assert(q->data.binaryheap.size < q->data.binaryheap.max_size);
00152
00153 if (q->data.binaryheap.elements[q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS] == NULL) {
00154
00155 assert((q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == 0);
00156 q->data.binaryheap.elements[q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00157 q->data.binaryheap.blocks++;
00158 #ifdef QUEUE_DEBUG
00159 printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks * BINARY_HEAP_BLOCKSIZE);
00160 #endif
00161 }
00162
00163
00164 BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority;
00165 BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item;
00166 q->data.binaryheap.size++;
00167
00168
00169
00170 {
00171 BinaryHeapNode temp;
00172 int i;
00173 int j;
00174
00175 i = q->data.binaryheap.size;
00176 while (i > 1) {
00177
00178 j = i / 2;
00179
00180 if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) {
00181 temp = BIN_HEAP_ARR(j);
00182 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
00183 BIN_HEAP_ARR(i) = temp;
00184 i = j;
00185 } else {
00186
00187 break;
00188 }
00189 }
00190 }
00191
00192 return true;
00193 }
00194
00195 static bool BinaryHeap_Delete(Queue *q, void *item, int priority)
00196 {
00197 uint i = 0;
00198
00199 #ifdef QUEUE_DEBUG
00200 printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size);
00201 #endif
00202
00203
00204 do {
00205 if (BIN_HEAP_ARR(i + 1).item == item) break;
00206 i++;
00207 } while (i < q->data.binaryheap.size);
00208
00209 if (i == q->data.binaryheap.size) return false;
00210
00211
00212 q->data.binaryheap.size--;
00213 BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1);
00214
00215
00216
00217 {
00218 uint j;
00219 BinaryHeapNode temp;
00220
00221
00222
00223 i++;
00224
00225 for (;;) {
00226 j = i;
00227
00228 if (2 * j + 1 <= q->data.binaryheap.size) {
00229
00230 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
00231
00232
00233 if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1;
00234
00235 } else if (2 * j <= q->data.binaryheap.size) {
00236 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
00237 }
00238
00239
00240 if (i != j) {
00241 temp = BIN_HEAP_ARR(j);
00242 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
00243 BIN_HEAP_ARR(i) = temp;
00244 } else {
00245
00246 break;
00247 }
00248 }
00249 }
00250
00251 return true;
00252 }
00253
00254 static void *BinaryHeap_Pop(Queue *q)
00255 {
00256 void *result;
00257
00258 #ifdef QUEUE_DEBUG
00259 printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size);
00260 #endif
00261
00262 if (q->data.binaryheap.size == 0) return NULL;
00263
00264
00265 result = BIN_HEAP_ARR(1).item;
00266
00267 BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority);
00268
00269 return result;
00270 }
00271
00272 void init_BinaryHeap(Queue *q, uint max_size)
00273 {
00274 assert(q != NULL);
00275 q->push = BinaryHeap_Push;
00276 q->pop = BinaryHeap_Pop;
00277 q->del = BinaryHeap_Delete;
00278 q->clear = BinaryHeap_Clear;
00279 q->free = BinaryHeap_Free;
00280 q->data.binaryheap.max_size = max_size;
00281 q->data.binaryheap.size = 0;
00282
00283
00284 q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
00285 q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00286 q->data.binaryheap.blocks = 1;
00287 #ifdef QUEUE_DEBUG
00288 printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE);
00289 #endif
00290 }
00291
00292
00293 #undef BIN_HEAP_ARR
00294
00295
00296
00297
00298
00299 void init_Hash(Hash *h, Hash_HashProc *hash, uint num_buckets)
00300 {
00301
00302 uint i;
00303
00304 assert(h != NULL);
00305 #ifdef HASH_DEBUG
00306 debug("Allocated hash: %p", h);
00307 #endif
00308 h->hash = hash;
00309 h->size = 0;
00310 h->num_buckets = num_buckets;
00311 h->buckets = (HashNode*)MallocT<byte>(num_buckets * (sizeof(*h->buckets) + sizeof(*h->buckets_in_use)));
00312 #ifdef HASH_DEBUG
00313 debug("Buckets = %p", h->buckets);
00314 #endif
00315 h->buckets_in_use = (bool*)(h->buckets + num_buckets);
00316 for (i = 0; i < num_buckets; i++) h->buckets_in_use[i] = false;
00317 }
00318
00319
00320 void delete_Hash(Hash *h, bool free_values)
00321 {
00322 uint i;
00323
00324
00325 for (i = 0; i < h->num_buckets; i++) {
00326 if (h->buckets_in_use[i]) {
00327 HashNode *node;
00328
00329
00330 if (free_values) free(h->buckets[i].value);
00331 node = h->buckets[i].next;
00332 while (node != NULL) {
00333 HashNode *prev = node;
00334
00335 node = node->next;
00336
00337 if (free_values) free(prev->value);
00338
00339 free(prev);
00340 }
00341 }
00342 }
00343 free(h->buckets);
00344
00345
00346 #ifdef HASH_DEBUG
00347 debug("Freeing Hash: %p", h);
00348 #endif
00349 }
00350
00351 #ifdef HASH_STATS
00352 static void stat_Hash(const Hash *h)
00353 {
00354 uint used_buckets = 0;
00355 uint max_collision = 0;
00356 uint max_usage = 0;
00357 uint usage[200];
00358 uint i;
00359
00360 for (i = 0; i < lengthof(usage); i++) usage[i] = 0;
00361 for (i = 0; i < h->num_buckets; i++) {
00362 uint collision = 0;
00363 if (h->buckets_in_use[i]) {
00364 const HashNode *node;
00365
00366 used_buckets++;
00367 for (node = &h->buckets[i]; node != NULL; node = node->next) collision++;
00368 if (collision > max_collision) max_collision = collision;
00369 }
00370 if (collision >= lengthof(usage)) collision = lengthof(usage) - 1;
00371 usage[collision]++;
00372 if (collision > 0 && usage[collision] >= max_usage) {
00373 max_usage = usage[collision];
00374 }
00375 }
00376 printf(
00377 "---\n"
00378 "Hash size: %d\n"
00379 "Nodes used: %d\n"
00380 "Non empty buckets: %d\n"
00381 "Max collision: %d\n",
00382 h->num_buckets, h->size, used_buckets, max_collision
00383 );
00384 printf("{ ");
00385 for (i = 0; i <= max_collision; i++) {
00386 if (usage[i] > 0) {
00387 printf("%d:%d ", i, usage[i]);
00388 #if 0
00389 if (i > 0) {
00390 uint j;
00391
00392 for (j = 0; j < usage[i] * 160 / 800; j++) putchar('#');
00393 }
00394 printf("\n");
00395 #endif
00396 }
00397 }
00398 printf ("}\n");
00399 }
00400 #endif
00401
00402 void clear_Hash(Hash *h, bool free_values)
00403 {
00404 uint i;
00405
00406 #ifdef HASH_STATS
00407 if (h->size > 2000) stat_Hash(h);
00408 #endif
00409
00410
00411 for (i = 0; i < h->num_buckets; i++) {
00412 if (h->buckets_in_use[i]) {
00413 HashNode *node;
00414
00415 h->buckets_in_use[i] = false;
00416
00417 if (free_values) free(h->buckets[i].value);
00418 node = h->buckets[i].next;
00419 while (node != NULL) {
00420 HashNode *prev = node;
00421
00422 node = node->next;
00423 if (free_values) free(prev->value);
00424 free(prev);
00425 }
00426 }
00427 }
00428 h->size = 0;
00429 }
00430
00438 static HashNode *Hash_FindNode(const Hash *h, uint key1, uint key2, HashNode** prev_out)
00439 {
00440 uint hash = h->hash(key1, key2);
00441 HashNode *result = NULL;
00442
00443 #ifdef HASH_DEBUG
00444 debug("Looking for %u, %u", key1, key2);
00445 #endif
00446
00447 if (!h->buckets_in_use[hash]) {
00448 if (prev_out != NULL) *prev_out = NULL;
00449 result = NULL;
00450
00451 } else if (h->buckets[hash].key1 == key1 && h->buckets[hash].key2 == key2) {
00452
00453 result = h->buckets + hash;
00454 if (prev_out != NULL) *prev_out = NULL;
00455 #ifdef HASH_DEBUG
00456 debug("Found in first node: %p", result);
00457 #endif
00458
00459 } else {
00460 HashNode *prev = h->buckets + hash;
00461 HashNode *node;
00462
00463 for (node = prev->next; node != NULL; node = node->next) {
00464 if (node->key1 == key1 && node->key2 == key2) {
00465
00466 result = node;
00467 #ifdef HASH_DEBUG
00468 debug("Found in other node: %p", result);
00469 #endif
00470 break;
00471 }
00472 prev = node;
00473 }
00474 if (prev_out != NULL) *prev_out = prev;
00475 }
00476 #ifdef HASH_DEBUG
00477 if (result == NULL) debug("Not found");
00478 #endif
00479 return result;
00480 }
00481
00482 void *Hash_Delete(Hash *h, uint key1, uint key2)
00483 {
00484 void *result;
00485 HashNode *prev;
00486 HashNode *node = Hash_FindNode(h, key1, key2, &prev);
00487
00488 if (node == NULL) {
00489
00490 result = NULL;
00491 } else if (prev == NULL) {
00492
00493
00494
00495 result = node->value;
00496 if (node->next != NULL) {
00497 HashNode *next = node->next;
00498
00499 *node = *next;
00500
00501 #ifndef NOFREE
00502 free(next);
00503 #endif
00504 } else {
00505
00506
00507 uint hash = h->hash(key1, key2);
00508 h->buckets_in_use[hash] = false;
00509 }
00510 } else {
00511
00512
00513 result = node->value;
00514
00515 prev->next = node->next;
00516
00517 #ifndef NOFREE
00518 free(node);
00519 #endif
00520 }
00521 if (result != NULL) h->size--;
00522 return result;
00523 }
00524
00525
00526 void *Hash_Set(Hash *h, uint key1, uint key2, void *value)
00527 {
00528 HashNode *prev;
00529 HashNode *node = Hash_FindNode(h, key1, key2, &prev);
00530
00531 if (node != NULL) {
00532
00533 void *result = node->value;
00534
00535 node->value = value;
00536 return result;
00537 }
00538
00539 if (prev == NULL) {
00540
00541 uint hash = h->hash(key1, key2);
00542 h->buckets_in_use[hash] = true;
00543 node = h->buckets + hash;
00544 } else {
00545
00546 node = MallocT<HashNode>(1);
00547 prev->next = node;
00548 }
00549 node->next = NULL;
00550 node->key1 = key1;
00551 node->key2 = key2;
00552 node->value = value;
00553 h->size++;
00554 return NULL;
00555 }
00556
00557 void *Hash_Get(const Hash *h, uint key1, uint key2)
00558 {
00559 HashNode *node = Hash_FindNode(h, key1, key2, NULL);
00560
00561 #ifdef HASH_DEBUG
00562 debug("Found node: %p", node);
00563 #endif
00564 return (node != NULL) ? node->value : NULL;
00565 }
00566
00567 uint Hash_Size(const Hash *h)
00568 {
00569 return h->size;
00570 }