12 #include "../../stdafx.h" 13 #include "../../core/alloc_func.hpp" 16 #include "../../safeguards.h" 26 const int BinaryHeap::BINARY_HEAP_BLOCKSIZE_MASK = BinaryHeap::BINARY_HEAP_BLOCKSIZE - 1;
39 for (i = 0; i < this->
blocks; i++) {
40 if (this->elements[i] == NULL) {
49 (this->size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
52 free(this->elements[i][j].item);
57 free(this->elements[i]);
58 this->elements[i] = NULL;
74 this->
Clear(free_values);
75 for (i = 0; i < this->
blocks; i++) {
76 if (this->elements[i] == NULL)
break;
77 free(this->elements[i]);
88 if (this->size == this->max_size)
return false;
89 assert(this->size < this->max_size);
93 assert((this->size & BINARY_HEAP_BLOCKSIZE_MASK) == 0);
99 this->
GetElement(this->size + 1).priority = priority;
141 if (this->
GetElement(i + 1).item == item)
break;
143 }
while (i < this->size);
145 if (i == this->size)
return false;
164 if (2 * j + 1 <= this->size) {
171 }
else if (2 * j <= this->size) {
198 if (this->size == 0)
return NULL;
214 this->max_size = max_size;
218 this->elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
219 this->elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
244 this->num_buckets = num_buckets;
245 this->buckets = (
HashNode*)MallocT<byte>(num_buckets * (
sizeof(*this->buckets) +
sizeof(*this->buckets_in_use)));
246 this->buckets_in_use = (
bool*)(this->buckets + num_buckets);
247 for (i = 0; i < num_buckets; i++) this->buckets_in_use[i] =
false;
260 for (i = 0; i < this->num_buckets; i++) {
261 if (this->buckets_in_use[i]) {
265 if (free_values)
free(this->buckets[i].value);
266 node = this->buckets[i].next;
267 while (node != NULL) {
272 if (free_values)
free(prev->value);
284 void Hash::PrintStatistics()
const 286 uint used_buckets = 0;
287 uint max_collision = 0;
292 for (i = 0; i <
lengthof(usage); i++) usage[i] = 0;
293 for (i = 0; i < this->num_buckets; i++) {
295 if (this->buckets_in_use[i]) {
299 for (node = &this->buckets[i]; node != NULL; node = node->next) collision++;
300 if (collision > max_collision) max_collision = collision;
304 if (collision > 0 && usage[collision] >= max_usage) {
305 max_usage = usage[collision];
312 "Non empty buckets: %d\n" 313 "Max collision: %d\n",
314 this->num_buckets, this->size, used_buckets, max_collision
317 for (i = 0; i <= max_collision; i++) {
319 printf(
"%d:%d ", i, usage[i]);
324 for (j = 0; j < usage[i] * 160 / 800; j++) putchar(
'#');
342 if (this->size > 2000) this->PrintStatistics();
346 for (i = 0; i < this->num_buckets; i++) {
347 if (this->buckets_in_use[i]) {
350 this->buckets_in_use[i] =
false;
352 if (free_values)
free(this->buckets[i].value);
353 node = this->buckets[i].next;
354 while (node != NULL) {
358 if (free_values)
free(prev->value);
376 uint hash = this->hash(key1, key2);
380 if (!this->buckets_in_use[hash]) {
381 if (prev_out != NULL) *prev_out = NULL;
384 }
else if (this->buckets[hash].key1 == key1 && this->buckets[hash].key2 == key2) {
386 result = this->buckets + hash;
387 if (prev_out != NULL) *prev_out = NULL;
390 HashNode *prev = this->buckets + hash;
393 for (node = prev->next; node != NULL; node = node->next) {
394 if (node->key1 == key1 && node->key2 == key2) {
401 if (prev_out != NULL) *prev_out = prev;
415 HashNode *node = this->FindNode(key1, key2, &prev);
420 }
else if (prev == NULL) {
424 result = node->value;
425 if (node->next != NULL) {
434 uint hash = this->hash(key1, key2);
435 this->buckets_in_use[hash] =
false;
440 result = node->value;
442 prev->next = node->next;
446 if (result != NULL) this->size--;
457 HashNode *node = this->FindNode(key1, key2, &prev);
461 void *result = node->value;
469 uint hash = this->hash(key1, key2);
470 this->buckets_in_use[hash] =
true;
471 node = this->buckets + hash;
474 node = MallocT<HashNode>(1);
491 HashNode *node = this->FindNode(key1, key2, NULL);
493 return (node != NULL) ? node->value : NULL;
void Free(bool free_values)
Frees the queue, by reclaiming all memory allocated by it.
void Delete(bool free_values)
Deletes the hash and cleans up.
void Clear(bool free_values)
Cleans the hash, but keeps the memory allocated.
BinaryHeapNode & GetElement(uint i)
Get an element from the #elements.
bool Delete(void *item, int priority)
Deletes the item from the queue.
void * Set(uint key1, uint key2, void *value)
Sets the value associated with the given key pair to the given value.
void Clear(bool free_values)
Clears the queue, by removing all values from it.
Binary heap implementation, hash implementation.
uint blocks
The amount of blocks for which space is reserved in elements.
void * DeleteValue(uint key1, uint key2)
Deletes the value with the specified key pair from the hash and returns that value.
uint Hash_HashProc(uint key1, uint key2)
Generates a hash code from the given key pair.
#define lengthof(x)
Return the length of an fixed size array.
void * Pop()
Pops the first element from the queue.
void Init(Hash_HashProc *hash, uint num_buckets)
Builds a new hash in an existing struct.
HashNode * FindNode(uint key1, uint key2, HashNode **prev_out) const
Finds the node that that saves this key pair.
void * Get(uint key1, uint key2) const
Gets the value associated with the given key pair, or NULL when it is not present.
void Init(uint max_size)
Initializes a binary heap and allocates internal memory for maximum of max_size elements.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
bool Push(void *item, int priority)
Pushes an element into the queue, at the appropriate place for the queue.
static const int BINARY_HEAP_BLOCKSIZE_BITS
The number of elements that will be malloc'd at a time.
static void CheckAllocationConstraints(size_t element_size, size_t num_elements)
Checks whether allocating memory would overflow size_t.