【问题标题】:Speclialized hashtable algorithms for dynamic/static/incremental data动态/静态/增量数据的专用哈希表算法
【发布时间】:2011-01-14 16:38:02
【问题描述】:

我有许多具有键值模式的数据集 - 即字符串键和指向数据的指针。现在它存储在哈希表中,每个表都有对应于哈希键的槽数组,并且在发生冲突时在每个有冲突的槽下形成一个链表(直接链接)。如果重要的话,所有都在 C 中实现(并且应该保留在 C 中)。

现在,数据实际上是 3 种略有不同的数据集:

  1. 可以随意更改某些集合(添加、删除、替换等)
  2. 对于某些集合,可以添加数据,但几乎从不替换/删除(即可能发生,但在实践中非常罕见)
  3. 对于某些集合,数据只添加一次,然后仅查找,一旦加载整个集合,它就永远不会更改。

当然,所有集合都必须尽可能快地支持查找,并且消耗最少的内存(尽管查找速度比大小更重要)。

所以问题是 - 是否有更好的哈希表结构/实现更适合特定情况?我怀疑对于第一种情况,链接是最好的,但不确定其他两种情况。

【问题讨论】:

  • 你事先知道套路吗?集合是有限的吗?多大?
  • C 语言中肯定有许多免费的哈希表实现。我建议使用其中之一,因为它们可能比您的代码更好。
  • @Moron:这些集合不是事先知道的,它们中的大多数都非常小(几十个元素),但有些可能很大,尤其是。静态的 - 多达数千甚至更多。
  • @Georg:我已经有了通用案例的链式哈希实现,而且效果很好。我正在寻找的是一个哈希实现的建议,它在特殊情况下会有更好的特性(比如加载后永远不会改变的静态数据)。
  • @Stasm:你有什么样的钥匙?整数?字符串?任何定义明确的结构?

标签: c algorithm hash hashtable lookup


【解决方案1】:

对存储在顺序内存中的键进行二分甚至线性搜索时,那些较小的集合(数十个元素)可能是最快的!

显然,密钥主体必须在顺序内存中,或者它们的散列中。但如果你能把它放到一两个 L1 cache.lines 中,它就会飞起来。

对于更大的哈希,直接链接可能会输给开放寻址?

您可以探索“cache conscious”哈希表并尝试。

wikipedia 文章详细讨论了缓存行,描述了要考虑的各种权衡。

【讨论】:

    【解决方案2】:

    如果您对哈希表中的每个存储桶都使用链表,那么您已经接受了现代 CPU 上相对较差的性能(链表的局部性较差,因此 CPU 缓存交互较差)。所以我可能不会担心优化其他特殊情况。但是,如果您想继续使用您正在使用的路径,这里有一些提示:

    对于“频繁更改”数据集和“几乎从不更改”的情况,每次从哈希表中读取一个项目时,将其移动到该存储桶的链表链的前面。对于一些更好的想法,尽管这篇论文专注于固定大小的键,但它是一个很好的起点Fast and Compact Hash Tables for Integer Keys

    对于“数据集永远不会改变”的情况,您应该研究完美的哈希生成器。如果您在编译时知道您的密钥,我在gperf 上取得了很好的结果。如果您的密钥在运行时才可用,请尝试C Minimal Perfect Hashing Library

    【讨论】:

    • 问题是,虽然数据是静态的,但事先并不知道 - 即假设您从用户提供的文件加载列表键/值对,然后必须多次查找这些数据。所以 gperf 可能无济于事 - 但一些运行时解决方案可能会。
    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    相关资源
    最近更新 更多