繁体   English   中英

如何修复此调整大小功能?

[英]How can I fix this resize function?

我正在学习数据结构。 我需要为哈希表(链接/存储桶)创建一个调整大小的函数。 我的代码可以编译,但是表大小从未改变。 有人可以看一下并给我一些有关调整大小功能中缺少的提示吗? 谢谢!

    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);
}

您没有释放旧表。 您正在释放刚分配的那个。 代替

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-> tableSize”不同,旧表中的存储区索引可能与新表中的存储区条目不同。

在resize()期间,请小心管理旧表的链接列表分配。 可以在新表中重新使用它们,但是在此处进行正确的编码可能会很困难。

以下是一些增强的想法...

PS还推荐

if (ht->count > (ht->tableSize * 8))

代替

if ((ht->count / (double) ht->tableSize) > 8.0)

PS还建议不要将桌子的大小增加一倍,而应增加四倍。 此外,将表的大小设置为素数也很不错。 用质数执行“%ht-> tableSize”有助于改善弱哈希函数的散布。

添加hashTableDelete()时,四倍效果很好。 使用delete函数,您可以再次调用resize函数,但是这次表正在缩小。 重要的是您的增长阈值(例如tablesize * 8)和收缩阈值必须不同。 如果两者差不多,则当表具有该临界大小时,如果您恰好要添加和删除,则可能会出现“散列混乱”的情况。 我喜欢将增长阈值设置为3、11、61、251,...(素数低于4 ** N),将收缩阈值设置为1、7、31、119,...(素数低于2 * 4 ** N),因此随着表的增长和收缩,将重新哈希保持在最低水平。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM