我正在学习数据结构。我需要为哈希表(链接/桶)创建一个resize函数。我的代码编译,但表大小永远不会改变。有人可以看看并给我一些关于我在调整大小功能中缺少什么的提示吗?谢谢!
struct hlink {
TYPE value;
struct hlink *next;
};
struct hashTable {
struct hlink **table;
int tableSize;
int count;
};
void initHashTable (struct hashTable *ht, int size ) {
assert (size > 0);
//allocate memory for table
ht->table = (struct hlink **) malloc(size * sizeof(struct hlink *));
assert(ht->table != 0);
//initialize empty link list
int i;
for (i = 0; i < size; i++)
{
ht->table[i] = 0;
}
//set tableSize to be size
ht->tableSize = size;
ht->count = 0;
}
void _resizeHashTable(struct hashTable *ht)
{
//create and initialize new tablesize
int new_tblSize = 2 * ht->tableSize;
//old list
struct hlink **oldList = ht->table;
//new list
struct hlink **newList = (struct hlink **) malloc(new_tblSize * sizeof(struct hlink*));
//Copy old values to new table
for (int i=0; i < new_tblSize; i++)
{
//compute hash value to find the new bucket
int hashIndex = HASH(oldList[i]->value) % new_tblSize;
if (hashIndex < 0)
hashIndex += new_tblSize;
newList[i]->value = oldList[i]->value;
newList[i]->next = newList[hashIndex];
}
//Assign table and tablesize back to the old table
free(ht->table);
ht->table = newList;
ht->tableSize = new_tblSize;
}
void hashTableAdd (struct hashTable *ht, TYPE newValue)
{
// compute hash value to find the correct bucket
int hashIndex = HASH(newValue) % ht->tableSize;
if (hashIndex < 0)
hashIndex += ht->tableSize;
struct hlink * newLink = (struct hlink *) malloc(sizeof(struct hlink));
assert(newLink != 0);
newLink->value = newValue;
newLink->next = ht->table[hashIndex];
ht->table[hashIndex] = newLink; //add to bucket
ht->count++;
if ((ht->count / (double) ht->tableSize) > 8.0)
_resizeHashTable(ht);
}
答案 0 :(得分:1)
你没有释放旧桌子。你正在释放刚分配的那个。而不是
ht->table = new_tbl;
...
free(new_tbl);
你应该
free(ht->table);
ht->table = new_tbl;
您的
也有问题//Copy old values to new table
for (int i=0; i < ht->tableSize; i++)
{
new_tbl[i] = ht->table[i];
}
如上所述复制表桶条目是不够的,但是桶链接列表中的每个条目都需要重新散列,因为您有新的表大小,因此可能是新的哈希索引。
int hashIndex = HASH(newValue) % ht->tableSize;
我建议您在调整大小时暂时浏览每个旧存储桶,然后查看每个链接列表条目并将其移动到新表。请记住,对于每个条目,由于不同的“%ht-&gt; tableSize”,旧表中的存储区索引可能与新表中的存储区条目不同。
在resize()期间,请注意管理旧表的链接列表分配。它们可以在新表中重复使用,但这里的正确编码可能具有挑战性。
以下只是一些改进的想法...
P上。 S.还推荐
if (ht->count > (ht->tableSize * 8))
而不是
if ((ht->count / (double) ht->tableSize) > 8.0)
P上。 S.还建议不要将桌子尺寸加倍,而是将它翻两番。此外,使表格大小是一个很好的选择。使用素数执行“%ht-&gt; tableSize”有助于改善弱哈希函数的分散。
添加hashTableDelete()时,Quadrupling具有良好的触感。使用删除功能,您可以再次调用resize函数,但这次,表正在缩小。重要的是,您的增长阈值(例如,表格大小* 8)和缩小阈值是不同的。如果大致相同,那么当表格具有该临界大小时,如果您恰好添加和删除,则可以获得“抖动”。我喜欢将我的增长阈值设置为3,11,61,251,...(素数低于4 ** N)和我的收缩阈值为1,7,31,119,......(素数低于2 * 4 ** N),因此随着表的增长和缩小,将重新散列保持在最小值。