10 #include "../../stdafx.h"
11 #include "../../core/alloc_func.hpp"
14 #include "../../safeguards.h"
24 const int BinaryHeap::BINARY_HEAP_BLOCKSIZE_MASK = BinaryHeap::BINARY_HEAP_BLOCKSIZE - 1;
37 for (i = 0; i < this->
blocks; i++) {
38 if (this->elements[i] ==
nullptr) {
47 (this->size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
50 free(this->elements[i][j].item);
55 free(this->elements[i]);
56 this->elements[i] =
nullptr;
72 this->
Clear(free_values);
73 for (i = 0; i < this->
blocks; i++) {
74 if (this->elements[i] ==
nullptr)
break;
75 free(this->elements[i]);
86 if (this->size == this->max_size)
return false;
87 assert(this->size < this->max_size);
91 assert((this->size & BINARY_HEAP_BLOCKSIZE_MASK) == 0);
97 this->
GetElement(this->size + 1).priority = priority;
139 if (this->
GetElement(i + 1).item == item)
break;
141 }
while (i < this->size);
143 if (i == this->size)
return false;
162 if (2 * j + 1 <= this->size) {
169 }
else if (2 * j <= this->size) {
196 if (this->size == 0)
return nullptr;
212 this->max_size = max_size;
216 this->elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
217 this->elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
242 this->num_buckets = num_buckets;
243 this->buckets = (
HashNode*)MallocT<byte>(num_buckets * (
sizeof(*this->buckets) +
sizeof(*this->buckets_in_use)));
244 this->buckets_in_use = (
bool*)(this->buckets + num_buckets);
245 for (i = 0; i < num_buckets; i++) this->buckets_in_use[i] =
false;
258 for (i = 0; i < this->num_buckets; i++) {
259 if (this->buckets_in_use[i]) {
263 if (free_values)
free(this->buckets[i].value);
264 node = this->buckets[i].next;
265 while (node !=
nullptr) {
270 if (free_values)
free(prev->value);
282 void Hash::PrintStatistics()
const
284 uint used_buckets = 0;
285 uint max_collision = 0;
290 for (i = 0; i <
lengthof(usage); i++) usage[i] = 0;
291 for (i = 0; i < this->num_buckets; i++) {
293 if (this->buckets_in_use[i]) {
297 for (node = &this->buckets[i]; node !=
nullptr; node = node->next) collision++;
298 if (collision > max_collision) max_collision = collision;
302 if (collision > 0 && usage[collision] >= max_usage) {
303 max_usage = usage[collision];
306 Debug(misc, 0,
"Hash size: {}, Nodes used: {}, Non empty buckets: {}, Max collision: {}",
307 this->num_buckets, this->size, used_buckets, max_collision
311 for (i = 0; i <= max_collision; i++) {
313 fmt::format_to(std::back_inserter(line),
"{}:{} ", i, usage[i]);
318 for (j = 0; j < usage[i] * 160 / 800; j++) line +=
"#";
325 Debug(misc, 0,
"{}", line);
337 if (this->size > 2000) this->PrintStatistics();
341 for (i = 0; i < this->num_buckets; i++) {
342 if (this->buckets_in_use[i]) {
345 this->buckets_in_use[i] =
false;
347 if (free_values)
free(this->buckets[i].value);
348 node = this->buckets[i].next;
349 while (node !=
nullptr) {
353 if (free_values)
free(prev->value);
371 uint hash = this->hash(tile, dir);
375 if (!this->buckets_in_use[hash]) {
376 if (prev_out !=
nullptr) *prev_out =
nullptr;
379 }
else if (this->buckets[hash].tile == tile && this->buckets[hash].dir == dir) {
381 result = this->buckets + hash;
382 if (prev_out !=
nullptr) *prev_out =
nullptr;
385 HashNode *prev = this->buckets + hash;
388 for (node = prev->next; node !=
nullptr; node = node->next) {
389 if (node->tile == tile && node->dir == dir) {
396 if (prev_out !=
nullptr) *prev_out = prev;
412 if (node ==
nullptr) {
415 }
else if (prev ==
nullptr) {
419 result = node->value;
420 if (node->next !=
nullptr) {
429 uint hash = this->hash(tile, dir);
430 this->buckets_in_use[hash] =
false;
435 result = node->value;
437 prev->next = node->next;
441 if (result !=
nullptr) this->size--;
454 if (node !=
nullptr) {
456 void *result = node->value;
462 if (prev ==
nullptr) {
464 uint hash = this->hash(tile, dir);
465 this->buckets_in_use[hash] =
true;
466 node = this->buckets + hash;
469 node = MallocT<HashNode>(1);
472 node->next =
nullptr;
488 return (node !=
nullptr) ? node->value :
nullptr;