哈希表如何用于动态长度数组?

问题描述

在数组长度固定的情况下,哈希表的时间复杂度为 O(1) 对我来说是有意义的。但是,我不明白哈希表如何用于动态长度的数组,例如链表。当数组的元素分散在整个内存中时,直接索引显然是不可能的。

解决方法

您是对的,将键实现为链表的哈希表不会O(1),因为键搜索是 O(n)。然而,链表并不是唯一的可扩展结构。

例如,您可以使用可调整大小的向量,例如每次需要扩展时大小加倍的向量。 无需O(n)搜索即可直接寻址,因此满足O(1)条件。

请记住,调整向量的大小几乎肯定会改变将项目分配到该向量的各个桶中的公式,这意味着您很有可能必须重新计算每个现有所在的桶项目已存储。

这仍然会摊销为 O(1),即使单个 insert 操作可能不得不执行 O(n) 重新分配,因为重新分配将不经常发生,并且很可能随着向量变大,随着时间的推移变得降低频率。

,

您仍然可以将链表的元素映射到哈希表。是的,确实我们事先不知道列表的大小,因此我们不能使用 C 样式或不可扩展的数组来表示我们的哈希表。这就是向量发挥作用的地方(如果您来自 Java,则使用 ArrayList)。

向量的速成课程将是:如果当前数组中没有更多空间,则创建一个双倍大小的新数组,并将之前的元素复制到其中。更正式地说,如果我们想将 n+1 元素插入到大小为 n 的数组中,那么它将创建一个大小为 2n 的新数组。对于下一次溢出,它将创建一个大小为 4n 的数组,依此类推。

以下代码可以将链表的值映射到哈希表中。

void map(Node* root) {
    vector<int> hash;

    while(root){
        hash[root->val]++;
        root = root->next;
    }

    for(int i = 0; i<hash.size(); i++){
        cout<<hash[i]<<" ";
    }
}