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