bool hashtable2_resize(hashtable2* table, unsigned new_size) { ASSERT(table != NULL); ASSERT(new_size != 0); new_size = dict_prime_geq(new_size); if (table->size == new_size) return true; if (table->count > new_size) { /* The number of records already in hashtable will not fit (must be a reduction in size). */ return false; } const unsigned old_size = table->size; const size_t old_count = table->count; hash_node *const old_table = table->table; table->table = MALLOC(new_size * sizeof(hash_node)); if (!table->table) { table->table = old_table; return false; } memset(table->table, 0, new_size * sizeof(hash_node)); table->size = new_size; table->count = 0; for (unsigned i = 0; i < old_size; i++) { if (old_table[i].hash) { bool inserted = false; void **datum_location = insert(table, old_table[i].key, old_table[i].hash, &inserted); if (!inserted || !datum_location) { FREE(table->table); table->table = old_table; table->size = old_size; table->count = old_count; return false; } *datum_location = old_table[i].datum; } } ASSERT(table->count == old_count); FREE(old_table); return true; }
bool hashtable_resize(hashtable* table, unsigned new_size) { ASSERT(table != NULL); ASSERT(new_size != 0); new_size = dict_prime_geq(new_size); if (table->size == new_size) return true; /* TODO: investigate whether using realloc would be advantageous. */ hash_node** ntable = MALLOC(new_size * sizeof(hash_node*)); if (!ntable) return false; memset(ntable, 0, new_size * sizeof(hash_node*)); for (unsigned i = 0; i < table->size; i++) { hash_node* node = table->table[i]; while (node) { hash_node* next = node->next; unsigned mhash = node->hash % new_size; hash_node* search = ntable[mhash]; hash_node* prev = NULL; while (search && node->hash >= search->hash) { prev = search; search = search->next; } if ((node->next = search) != NULL) search->prev = node; if ((node->prev = prev) != NULL) prev->next = node; else ntable[mhash] = node; node = next; } } FREE(table->table); table->table = ntable; table->size = new_size; return true; }
hashtable2* hashtable2_new(dict_compare_func cmp_func, dict_hash_func hash_func, dict_delete_func del_func, unsigned initial_size) { ASSERT(hash_func != NULL); ASSERT(initial_size != 0); hashtable2* table = MALLOC(sizeof(*table)); if (table) { table->size = dict_prime_geq(initial_size); table->table = MALLOC(table->size * sizeof(hash_node)); if (!table->table) { FREE(table); return NULL; } memset(table->table, 0, table->size * sizeof(hash_node)); table->cmp_func = cmp_func ? cmp_func : dict_ptr_cmp; table->hash_func = hash_func; table->del_func = del_func; table->count = 0; } return table; }