HashTable *hash_table_new(HashTableHashFunc hash_func, HashTableEqualFunc equal_func) { HashTable *hash_table; /* Allocate a new hash table structure */ hash_table = (HashTable *) malloc(sizeof(HashTable)); if (hash_table == NULL) { return NULL; } hash_table->hash_func = hash_func; hash_table->equal_func = equal_func; hash_table->key_free_func = NULL; hash_table->value_free_func = NULL; hash_table->entries = 0; hash_table->prime_index = 0; /* Allocate the table */ if (!hash_table_allocate_table(hash_table, 0)) { free(hash_table); return NULL; } return hash_table; }
int hash_table_resize(HashTable *hash_table) { HashTableEntry **old_table; unsigned long long int old_table_size; int old_prime_index; HashTableEntry *rover; HashTableEntry *next; unsigned long long int index; unsigned long long int i; int increment = 0; // GROW if((hash_table->entries * 2) / hash_table->table_size > 0) { do { /* Table is more than 1/2 full */ increment++; } while ((hash_table->entries * 2) / getHashTableSizeWithIncrement(hash_table, increment) > 0); } // SHRINK else if((hash_table->entries * 8) / hash_table->table_size == 0) { do { // Are we already as small as possible? if(getHashTableSizeWithIncrement(hash_table, increment) <= hash_table_primes[0]) { break; } /* Table is less than 1/8 full */ increment--; } while ((hash_table->entries * 8) / getHashTableSizeWithIncrement(hash_table, increment) <= 0); } if(increment != 0) { /* Store a copy of the old table */ old_table = hash_table->table; old_table_size = hash_table->table_size; old_prime_index = hash_table->prime_index; if (!hash_table_allocate_table(hash_table, increment)) { /* Failed to allocate the new table */ printf("CRITICAL: FAILED TO ALLOCATE HASH TABLE!\n"); hash_table->table = old_table; hash_table->table_size = old_table_size; hash_table->prime_index = old_prime_index; return 0; } /* Link all entries from all chains into the new table */ for (i=0; i<old_table_size; ++i) { rover = old_table[i]; while (rover != NULL) { next = rover->next; /* Find the index into the new table */ index = hash_table->hash_func(rover->key) % hash_table->table_size; /* Link this entry into the chain */ rover->next = hash_table->table[index]; hash_table->table[index] = rover; /* Advance to next in the chain */ rover = next; } } /* Free the old table */ free(old_table); } return 1; }
static int hash_table_enlarge(HashTable *hash_table) { HashTableEntry **old_table; unsigned int old_table_size; unsigned int old_prime_index; HashTableEntry *rover; HashTableEntry *next; unsigned int index; unsigned int i; /* Store a copy of the old table */ old_table = hash_table->table; old_table_size = hash_table->table_size; old_prime_index = hash_table->prime_index; /* Allocate a new, larger table */ ++hash_table->prime_index; if (!hash_table_allocate_table(hash_table)) { /* Failed to allocate the new table */ hash_table->table = old_table; hash_table->table_size = old_table_size; hash_table->prime_index = old_prime_index; return 0; } /* Link all entries from all chains into the new table */ for (i=0; i<old_table_size; ++i) { rover = old_table[i]; while (rover != NULL) { next = rover->next; /* Find the index into the new table */ index = hash_table->hash_func(rover->key) % hash_table->table_size; /* Link this entry into the chain */ rover->next = hash_table->table[index]; hash_table->table[index] = rover; /* Advance to next in the chain */ rover = next; } } /* Free the old table */ free(old_table); return 1; }