【问题标题】:Hash table - adding a rehash to resize method哈希表 - 添加 rehash 以调整大小的方法
【发布时间】:2020-11-29 17:39:29
【问题描述】:

我正在使用链式处理哈希表,但不知道在调整大小时应该如何重新哈希整个表。我正在考虑在 resize 方法中插入所有带有新哈希码的元素,但我不知道如何......你能给我一个提示或什么吗? 这是重新散列(我的意思是调整大小,还没有重新散列)方法:

void rehash()
{
    if (current_size >= load * size) {
        int newsize = size * cap;
        Node** tmp = new Node * [newsize];
        for (int i = 0; i < size; i++) 
        {
            tmp[i] = hashtable[i];
        }
        for (int i = size; i < newsize; ++i) 
        {
            tmp[i] = NULL;
        }
        delete[] hashtable;
        hashtable = tmp;
        size = newsize;
    }
}

如果有帮助,插入方法:

void addTo(string key, V value)
{
    rehash();
    int index = hashFunction(key);
    if (hashtable[index] == NULL)
    {
        Node* newpair = new Node(key, value);
        hashtable[index] = newpair;
        hashtable[index]->data = newpair;
    }
    else
    {
        Node* tmp = hashtable[index];
        Node* newpair = new Node(key, value);
        Node* newnode = new Node;
        newnode->data = newpair;
        newnode->next = NULL;
        while (tmp->next != NULL)
        {
            tmp = tmp->next;
        }
        tmp->next = newnode;
        
    }
    current_size++;
}

谢谢。

【问题讨论】:

  • 当你增加表大小时,一些值可能会进入新表的后部,size &lt;= i &lt; newsize。您可以保留旧表的句柄,使用所有NULLs 分配一个新大小的新表,然后遍历旧表并将所有条目插入到具有addTo 的新表中。然后删除旧表。
  • 我推荐一种结构化的方法:假设你的类被称为hash_table,然后当你意识到你需要增加容量时,创建一个新的hash_table - 为构造函数指定更大的表大小 - 然后迭代当前元素,将每个元素插入新的hash_table,然后将swap(*this, 插入新的hash_table。这样,您就可以重用您应该已经使用的函数 - 构造函数、迭代、插入、交换 - 用于固定大小的表。
  • 感谢您的回答。我现在明白我应该怎么做,但不知道如何将我的 addTo 方法与新表一起使用
  • 显然,您有一个由tablesize 定义的全局哈希表,并且您的所有函数都对这些变量进行操作。您的代码创建一个新数组,然后设置这些变量。如果你反过来做——将旧表保存在局部变量中,并将全局哈希表设置为新数组——然后你可以使用你已经拥有的函数来填充新表。
  • (但我使用addTo 的建议并不理想,因为它会创建新节点并且您必须删除旧节点。更好的解决方案是将节点移动到它们的新的桶。因为您已经知道您没有重复的键(但您的插入函数不会强制执行),您可以将节点作为每个桶的新头插入。)

标签: c++ algorithm hashmap


【解决方案1】:

当您增加哈希表的大小时,某些键的关联存储桶可能会发生变化。您的代码只是从前面部分复制列表,这意味着在表中无法再找到某些值。 (例如,哈希码为 13 的键在大小为 4 的表中的索引为 1,但将大小增加到 8 后,索引将变为 5。)

您分配新数组的基本方法是正确的,但您必须将节点放在正确的存储桶中。因为你有一个链表,你可以访问旧表的每个桶,并在有一个时提取第一个节点,然后将其放入具有正确新索引的桶中:

void rehash()
{
    if (current_size >= load * size) {
        size_t newsize = size * cap;
        Node** tmp = new Node * [newsize];

        for (size_t i = 0; i < newsize; ++i) {
            tmp[i] = NULL;
        }

        for (size_t i = 0; i < size; i++) {
            while (hashtable[i]) {
                Node *node = hashtable[i];
                size_t index = hashFunction(node->key);

                // remove node from old table ...
                hashtable[i] = node->next;

                // ... and insert into new one
                node->next = tmp[index];
                tmp[index] = node;                    
            }
        }

        // replace hash table
        delete[] hashtable;
        hashtable = tmp;
        size = newsize;
    }
}

这可行。 (但我没有测试过。)

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 2012-10-14
    • 1970-01-01
    • 2011-06-24
    • 2013-12-21
    • 2021-03-14
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多