Go to the documentation of this file.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
00022 const int BinaryHeap::BINARY_HEAP_BLOCKSIZE_BITS = 10;
00023 const int BinaryHeap::BINARY_HEAP_BLOCKSIZE = 1 << BinaryHeap::BINARY_HEAP_BLOCKSIZE_BITS;
00024 const int BinaryHeap::BINARY_HEAP_BLOCKSIZE_MASK = BinaryHeap::BINARY_HEAP_BLOCKSIZE - 1;
00025
00031 void BinaryHeap::Clear(bool free_values)
00032 {
00033
00034 uint i;
00035 uint j;
00036
00037 for (i = 0; i < this->blocks; i++) {
00038 if (this->elements[i] == NULL) {
00039
00040 break;
00041 }
00042
00043 if (free_values) {
00044 for (j = 0; j < (1 << BINARY_HEAP_BLOCKSIZE_BITS); j++) {
00045
00046 if ((this->size >> BINARY_HEAP_BLOCKSIZE_BITS) == i &&
00047 (this->size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
00048 break;
00049 }
00050 free(this->elements[i][j].item);
00051 }
00052 }
00053 if (i != 0) {
00054
00055 free(this->elements[i]);
00056 this->elements[i] = NULL;
00057 }
00058 }
00059 this->size = 0;
00060 this->blocks = 1;
00061 }
00062
00068 void BinaryHeap::Free(bool free_values)
00069 {
00070 uint i;
00071
00072 this->Clear(free_values);
00073 for (i = 0; i < this->blocks; i++) {
00074 if (this->elements[i] == NULL) break;
00075 free(this->elements[i]);
00076 }
00077 free(this->elements);
00078 }
00079
00084 bool BinaryHeap::Push(void *item, int priority)
00085 {
00086 if (this->size == this->max_size) return false;
00087 assert(this->size < this->max_size);
00088
00089 if (this->elements[this->size >> BINARY_HEAP_BLOCKSIZE_BITS] == NULL) {
00090
00091 assert((this->size & BINARY_HEAP_BLOCKSIZE_MASK) == 0);
00092 this->elements[this->size >> BINARY_HEAP_BLOCKSIZE_BITS] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00093 this->blocks++;
00094 }
00095
00096
00097 this->GetElement(this->size + 1).priority = priority;
00098 this->GetElement(this->size + 1).item = item;
00099 this->size++;
00100
00101
00102
00103 {
00104 BinaryHeapNode temp;
00105 int i;
00106 int j;
00107
00108 i = this->size;
00109 while (i > 1) {
00110
00111 j = i / 2;
00112
00113 if (this->GetElement(i).priority <= this->GetElement(j).priority) {
00114 temp = this->GetElement(j);
00115 this->GetElement(j) = this->GetElement(i);
00116 this->GetElement(i) = temp;
00117 i = j;
00118 } else {
00119
00120 break;
00121 }
00122 }
00123 }
00124
00125 return true;
00126 }
00127
00133 bool BinaryHeap::Delete(void *item, int priority)
00134 {
00135 uint i = 0;
00136
00137
00138 do {
00139 if (this->GetElement(i + 1).item == item) break;
00140 i++;
00141 } while (i < this->size);
00142
00143 if (i == this->size) return false;
00144
00145
00146 this->size--;
00147 this->GetElement(i + 1) = this->GetElement(this->size + 1);
00148
00149
00150
00151 {
00152 uint j;
00153 BinaryHeapNode temp;
00154
00155
00156
00157 i++;
00158
00159 for (;;) {
00160 j = i;
00161
00162 if (2 * j + 1 <= this->size) {
00163
00164 if (this->GetElement(j).priority >= this->GetElement(2 * j).priority) i = 2 * j;
00165
00166
00167 if (this->GetElement(i).priority >= this->GetElement(2 * j + 1).priority) i = 2 * j + 1;
00168
00169 } else if (2 * j <= this->size) {
00170 if (this->GetElement(j).priority >= this->GetElement(2 * j).priority) i = 2 * j;
00171 }
00172
00173
00174 if (i != j) {
00175 temp = this->GetElement(j);
00176 this->GetElement(j) = this->GetElement(i);
00177 this->GetElement(i) = temp;
00178 } else {
00179
00180 break;
00181 }
00182 }
00183 }
00184
00185 return true;
00186 }
00187
00192 void *BinaryHeap::Pop()
00193 {
00194 void *result;
00195
00196 if (this->size == 0) return NULL;
00197
00198
00199 result = this->GetElement(1).item;
00200
00201 this->Delete(this->GetElement(1).item, this->GetElement(1).priority);
00202
00203 return result;
00204 }
00205
00210 void BinaryHeap::Init(uint max_size)
00211 {
00212 this->max_size = max_size;
00213 this->size = 0;
00214
00215
00216 this->elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
00217 this->elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00218 this->blocks = 1;
00219 }
00220
00221
00222 #undef BIN_HEAP_ARR
00223
00224
00225
00226
00227
00232 void Hash::Init(Hash_HashProc *hash, uint num_buckets)
00233 {
00234
00235 uint i;
00236
00237 this->hash = hash;
00238 this->size = 0;
00239 this->num_buckets = num_buckets;
00240 this->buckets = (HashNode*)MallocT<byte>(num_buckets * (sizeof(*this->buckets) + sizeof(*this->buckets_in_use)));
00241 this->buckets_in_use = (bool*)(this->buckets + num_buckets);
00242 for (i = 0; i < num_buckets; i++) this->buckets_in_use[i] = false;
00243 }
00244
00250 void Hash::Delete(bool free_values)
00251 {
00252 uint i;
00253
00254
00255 for (i = 0; i < this->num_buckets; i++) {
00256 if (this->buckets_in_use[i]) {
00257 HashNode *node;
00258
00259
00260 if (free_values) free(this->buckets[i].value);
00261 node = this->buckets[i].next;
00262 while (node != NULL) {
00263 HashNode *prev = node;
00264
00265 node = node->next;
00266
00267 if (free_values) free(prev->value);
00268
00269 free(prev);
00270 }
00271 }
00272 }
00273 free(this->buckets);
00274
00275
00276 }
00277
00278 #ifdef HASH_STATS
00279 void Hash::PrintStatistics() const
00280 {
00281 uint used_buckets = 0;
00282 uint max_collision = 0;
00283 uint max_usage = 0;
00284 uint usage[200];
00285 uint i;
00286
00287 for (i = 0; i < lengthof(usage); i++) usage[i] = 0;
00288 for (i = 0; i < this->num_buckets; i++) {
00289 uint collision = 0;
00290 if (this->buckets_in_use[i]) {
00291 const HashNode *node;
00292
00293 used_buckets++;
00294 for (node = &this->buckets[i]; node != NULL; node = node->next) collision++;
00295 if (collision > max_collision) max_collision = collision;
00296 }
00297 if (collision >= lengthof(usage)) collision = lengthof(usage) - 1;
00298 usage[collision]++;
00299 if (collision > 0 && usage[collision] >= max_usage) {
00300 max_usage = usage[collision];
00301 }
00302 }
00303 printf(
00304 "---\n"
00305 "Hash size: %d\n"
00306 "Nodes used: %d\n"
00307 "Non empty buckets: %d\n"
00308 "Max collision: %d\n",
00309 this->num_buckets, this->size, used_buckets, max_collision
00310 );
00311 printf("{ ");
00312 for (i = 0; i <= max_collision; i++) {
00313 if (usage[i] > 0) {
00314 printf("%d:%d ", i, usage[i]);
00315 #if 0
00316 if (i > 0) {
00317 uint j;
00318
00319 for (j = 0; j < usage[i] * 160 / 800; j++) putchar('#');
00320 }
00321 printf("\n");
00322 #endif
00323 }
00324 }
00325 printf ("}\n");
00326 }
00327 #endif
00328
00332 void Hash::Clear(bool free_values)
00333 {
00334 uint i;
00335
00336 #ifdef HASH_STATS
00337 if (this->size > 2000) this->PrintStatistics();
00338 #endif
00339
00340
00341 for (i = 0; i < this->num_buckets; i++) {
00342 if (this->buckets_in_use[i]) {
00343 HashNode *node;
00344
00345 this->buckets_in_use[i] = false;
00346
00347 if (free_values) free(this->buckets[i].value);
00348 node = this->buckets[i].next;
00349 while (node != NULL) {
00350 HashNode *prev = node;
00351
00352 node = node->next;
00353 if (free_values) free(prev->value);
00354 free(prev);
00355 }
00356 }
00357 }
00358 this->size = 0;
00359 }
00360
00369 HashNode *Hash::FindNode(uint key1, uint key2, HashNode** prev_out) const
00370 {
00371 uint hash = this->hash(key1, key2);
00372 HashNode *result = NULL;
00373
00374
00375 if (!this->buckets_in_use[hash]) {
00376 if (prev_out != NULL) *prev_out = NULL;
00377 result = NULL;
00378
00379 } else if (this->buckets[hash].key1 == key1 && this->buckets[hash].key2 == key2) {
00380
00381 result = this->buckets + hash;
00382 if (prev_out != NULL) *prev_out = NULL;
00383
00384 } else {
00385 HashNode *prev = this->buckets + hash;
00386 HashNode *node;
00387
00388 for (node = prev->next; node != NULL; node = node->next) {
00389 if (node->key1 == key1 && node->key2 == key2) {
00390
00391 result = node;
00392 break;
00393 }
00394 prev = node;
00395 }
00396 if (prev_out != NULL) *prev_out = prev;
00397 }
00398 return result;
00399 }
00400
00406 void *Hash::DeleteValue(uint key1, uint key2)
00407 {
00408 void *result;
00409 HashNode *prev;
00410 HashNode *node = this->FindNode(key1, key2, &prev);
00411
00412 if (node == NULL) {
00413
00414 result = NULL;
00415 } else if (prev == NULL) {
00416
00417
00418
00419 result = node->value;
00420 if (node->next != NULL) {
00421 HashNode *next = node->next;
00422
00423 *node = *next;
00424
00425 free(next);
00426 } else {
00427
00428
00429 uint hash = this->hash(key1, key2);
00430 this->buckets_in_use[hash] = false;
00431 }
00432 } else {
00433
00434
00435 result = node->value;
00436
00437 prev->next = node->next;
00438
00439 free(node);
00440 }
00441 if (result != NULL) this->size--;
00442 return result;
00443 }
00444
00449 void *Hash::Set(uint key1, uint key2, void *value)
00450 {
00451 HashNode *prev;
00452 HashNode *node = this->FindNode(key1, key2, &prev);
00453
00454 if (node != NULL) {
00455
00456 void *result = node->value;
00457
00458 node->value = value;
00459 return result;
00460 }
00461
00462 if (prev == NULL) {
00463
00464 uint hash = this->hash(key1, key2);
00465 this->buckets_in_use[hash] = true;
00466 node = this->buckets + hash;
00467 } else {
00468
00469 node = MallocT<HashNode>(1);
00470 prev->next = node;
00471 }
00472 node->next = NULL;
00473 node->key1 = key1;
00474 node->key2 = key2;
00475 node->value = value;
00476 this->size++;
00477 return NULL;
00478 }
00479
00484 void *Hash::Get(uint key1, uint key2) const
00485 {
00486 HashNode *node = this->FindNode(key1, key2, NULL);
00487
00488 return (node != NULL) ? node->value : NULL;
00489 }