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
00238 CheckAllocationConstraints(sizeof(*this->buckets) + sizeof(*this->buckets_in_use), num_buckets);
00239
00240 this->hash = hash;
00241 this->size = 0;
00242 this->num_buckets = num_buckets;
00243 this->buckets = (HashNode*)MallocT<byte>(num_buckets * (sizeof(*this->buckets) + sizeof(*this->buckets_in_use)));
00244 this->buckets_in_use = (bool*)(this->buckets + num_buckets);
00245 for (i = 0; i < num_buckets; i++) this->buckets_in_use[i] = false;
00246 }
00247
00253 void Hash::Delete(bool free_values)
00254 {
00255 uint i;
00256
00257
00258 for (i = 0; i < this->num_buckets; i++) {
00259 if (this->buckets_in_use[i]) {
00260 HashNode *node;
00261
00262
00263 if (free_values) free(this->buckets[i].value);
00264 node = this->buckets[i].next;
00265 while (node != NULL) {
00266 HashNode *prev = node;
00267
00268 node = node->next;
00269
00270 if (free_values) free(prev->value);
00271
00272 free(prev);
00273 }
00274 }
00275 }
00276 free(this->buckets);
00277
00278
00279 }
00280
00281 #ifdef HASH_STATS
00282 void Hash::PrintStatistics() const
00283 {
00284 uint used_buckets = 0;
00285 uint max_collision = 0;
00286 uint max_usage = 0;
00287 uint usage[200];
00288 uint i;
00289
00290 for (i = 0; i < lengthof(usage); i++) usage[i] = 0;
00291 for (i = 0; i < this->num_buckets; i++) {
00292 uint collision = 0;
00293 if (this->buckets_in_use[i]) {
00294 const HashNode *node;
00295
00296 used_buckets++;
00297 for (node = &this->buckets[i]; node != NULL; node = node->next) collision++;
00298 if (collision > max_collision) max_collision = collision;
00299 }
00300 if (collision >= lengthof(usage)) collision = lengthof(usage) - 1;
00301 usage[collision]++;
00302 if (collision > 0 && usage[collision] >= max_usage) {
00303 max_usage = usage[collision];
00304 }
00305 }
00306 printf(
00307 "---\n"
00308 "Hash size: %d\n"
00309 "Nodes used: %d\n"
00310 "Non empty buckets: %d\n"
00311 "Max collision: %d\n",
00312 this->num_buckets, this->size, used_buckets, max_collision
00313 );
00314 printf("{ ");
00315 for (i = 0; i <= max_collision; i++) {
00316 if (usage[i] > 0) {
00317 printf("%d:%d ", i, usage[i]);
00318 #if 0
00319 if (i > 0) {
00320 uint j;
00321
00322 for (j = 0; j < usage[i] * 160 / 800; j++) putchar('#');
00323 }
00324 printf("\n");
00325 #endif
00326 }
00327 }
00328 printf ("}\n");
00329 }
00330 #endif
00331
00335 void Hash::Clear(bool free_values)
00336 {
00337 uint i;
00338
00339 #ifdef HASH_STATS
00340 if (this->size > 2000) this->PrintStatistics();
00341 #endif
00342
00343
00344 for (i = 0; i < this->num_buckets; i++) {
00345 if (this->buckets_in_use[i]) {
00346 HashNode *node;
00347
00348 this->buckets_in_use[i] = false;
00349
00350 if (free_values) free(this->buckets[i].value);
00351 node = this->buckets[i].next;
00352 while (node != NULL) {
00353 HashNode *prev = node;
00354
00355 node = node->next;
00356 if (free_values) free(prev->value);
00357 free(prev);
00358 }
00359 }
00360 }
00361 this->size = 0;
00362 }
00363
00372 HashNode *Hash::FindNode(uint key1, uint key2, HashNode** prev_out) const
00373 {
00374 uint hash = this->hash(key1, key2);
00375 HashNode *result = NULL;
00376
00377
00378 if (!this->buckets_in_use[hash]) {
00379 if (prev_out != NULL) *prev_out = NULL;
00380 result = NULL;
00381
00382 } else if (this->buckets[hash].key1 == key1 && this->buckets[hash].key2 == key2) {
00383
00384 result = this->buckets + hash;
00385 if (prev_out != NULL) *prev_out = NULL;
00386
00387 } else {
00388 HashNode *prev = this->buckets + hash;
00389 HashNode *node;
00390
00391 for (node = prev->next; node != NULL; node = node->next) {
00392 if (node->key1 == key1 && node->key2 == key2) {
00393
00394 result = node;
00395 break;
00396 }
00397 prev = node;
00398 }
00399 if (prev_out != NULL) *prev_out = prev;
00400 }
00401 return result;
00402 }
00403
00409 void *Hash::DeleteValue(uint key1, uint key2)
00410 {
00411 void *result;
00412 HashNode *prev;
00413 HashNode *node = this->FindNode(key1, key2, &prev);
00414
00415 if (node == NULL) {
00416
00417 result = NULL;
00418 } else if (prev == NULL) {
00419
00420
00421
00422 result = node->value;
00423 if (node->next != NULL) {
00424 HashNode *next = node->next;
00425
00426 *node = *next;
00427
00428 free(next);
00429 } else {
00430
00431
00432 uint hash = this->hash(key1, key2);
00433 this->buckets_in_use[hash] = false;
00434 }
00435 } else {
00436
00437
00438 result = node->value;
00439
00440 prev->next = node->next;
00441
00442 free(node);
00443 }
00444 if (result != NULL) this->size--;
00445 return result;
00446 }
00447
00452 void *Hash::Set(uint key1, uint key2, void *value)
00453 {
00454 HashNode *prev;
00455 HashNode *node = this->FindNode(key1, key2, &prev);
00456
00457 if (node != NULL) {
00458
00459 void *result = node->value;
00460
00461 node->value = value;
00462 return result;
00463 }
00464
00465 if (prev == NULL) {
00466
00467 uint hash = this->hash(key1, key2);
00468 this->buckets_in_use[hash] = true;
00469 node = this->buckets + hash;
00470 } else {
00471
00472 node = MallocT<HashNode>(1);
00473 prev->next = node;
00474 }
00475 node->next = NULL;
00476 node->key1 = key1;
00477 node->key2 = key2;
00478 node->value = value;
00479 this->size++;
00480 return NULL;
00481 }
00482
00487 void *Hash::Get(uint key1, uint key2) const
00488 {
00489 HashNode *node = this->FindNode(key1, key2, NULL);
00490
00491 return (node != NULL) ? node->value : NULL;
00492 }