【问题标题】:Double Hashing - remove and rehash function双散列 - 删除和重新散列功能
【发布时间】:2015-01-28 17:01:38
【问题描述】:

我正在处理哈希映射,但在使用双哈希开放地址样式映射的删除功能时遇到了问题。假设我在大小为 10 的表上插入,我的 2 个哈希函数如下:

int hash( int key, std::size_t M ) { return key % M; }
int hash2( int key, std::size_t M ) { return key % (M-1) + 1; }

如果我使用键 0、10 和 20 插入项目,这些项目将转到位置 0、2 和 3。

<[ 0:A, - , 10:B, 20:C, - , - , - , - , - , - ]>

但是,当删除一个项目时,我想删除该项目并重新散列同一集群中的以下项目。当我删除密钥为 0 的项目时,它会发现要删除的项目没有问题。但是,它现在需要跳转到索引 2 - 但它不能因为它使用密钥 0 作为它的增量,所以它跳转到索引 1。因此,它永远不会在集群中找到后续项目。我该怎么做???

【问题讨论】:

    标签: c++ hash hashmap double-hashing


    【解决方案1】:

    通常,您可以通过在该位置放置已删除标记来删除项目。出于搜索的目的,它被占用,因此碰撞并需要探测才能找到的项目不是孤立的。但是在插入时,您可以重复使用该位置。如果表中已删除标记的数量变大,您可以重新哈希表以清理它。

    本讲详细讲解:Open Addressing

    【讨论】:

    • 好的。但是,假设每次我删除某些内容时,我都想重新散列该集群中的所有内容。如何在不知道其键的情况下到达下一个项目?
    • 我不认为你可以。这就是您标记删除或重新散列整个表的原因。
    • 哦,伙计。好的。什么会更有效率。在节点类中有一个名为“deleted”的布尔值,还是保存一个包含已删除索引的整数向量?
    • 你的节点类是什么样的?如果您的表包含对象引用,您可以创建一个“已删除”对象作为您的标记。如果您的表包含整数之类的东西,则不能这样做,因为任何标记值都可能是实际值。您可以在评论时将删除的信息保存在节点中,也可以在已删除的表中保存。我会在节点中使用。如果您有一个已删除的表,则必须对其进行线性搜索。这是时间与空间的权衡。但是根据你的节点现在是什么,它可能不需要额外的空间。
    • 不是mark_deleted的想法,我认为删除时我会搜索表,如果删除节点的hash1函数与这个相同,我会重新插入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2011-07-03
    • 2011-12-25
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多