【问题标题】:Is it better to build a hash table from an existing array than to create a hash table first then insert all the elements?从现有数组构建哈希表比先创建哈希表然后插入所有元素更好吗?
【发布时间】:2016-01-19 08:48:24
【问题描述】:

是否有任何实现可以在通用散列中选择几个散列函数并尝试这些函数以将总冲突减少到可接受的水平并以最少的冲突返回最佳结果?

如果有,从现有数组构建哈希表比先创建哈希表然后插入所有元素可靠得多,不是吗?

以下段落来自算法简介

"如果恶意攻击者选择要通过某个固定散列函数散列的密钥,则攻击者可以选择 n 个全部散列到同一槽的密钥,从而产生平均检索时间为 ‚.n/。任何固定散列函数很容易受到这种可怕的最坏情况行为的影响;改善这种情况的唯一有效方法是随机选择散列函数,这种方式与实际存储的密钥无关。这种称为通用散列的方法可以无论对手选择哪个键,平均都会产生可证明的良好性能。

在通用散列中,在执行开始时我们选择散列函数 从精心设计的一类函数中随机抽取。与快速排序的情况一样,随机化保证没有单个输入总是会引发最坏情况的行为。因为我们随机选择散列函数,算法在每次执行时表现不同,即使对于相同的输入,保证良好的 任何输入的平均情况下的性能。回到编译器的例子 符号表,我们发现程序员对标识符的选择现在不会导致哈希性能一直很差。只有当编译器选择了一个随机散列函数导致标识符集散列效果不佳时才会出现性能差,但这种情况发生的概率很小,并且对于任何相同大小的标识符集都是相同的。”

【问题讨论】:

  • doc.qt.io/qt-5/qhash.html 中描述的行为为“为了避免这种最坏情况的行为,qHash() 完成的哈希值计算可以通过随机种子进行盐渍化,从而使攻击无效。范围。这个种子由 QHash 每个进程自动生成一次,然后由 QHash 作为 qHash() 函数的双参数重载的第二个参数传递。可能会让人头疼,因为存储 QHash 派生图的程序很难比较相同代码的两次连续运行的结果。

标签: c++ algorithm hash


【解决方案1】:

如果您事先知道密钥,则可以使用perfect hashing 以避免任何冲突。因此,如果您在某处拥有所有元素(如在您的示例中,在一个数组中),并且不会有新的插入,那么当然,您可以做得更好。

问题是,在真正的应用程序中,键通常来来去去。表格在不断变化。

我不了解实现,但一如既往地归结为权衡。您正在尝试以额外的安全性来换取快速查找,并且您将付出额外的代码复杂性和减速以及潜在成本高昂的插入,当有很多冲突时会重新创建散列。但是你真的需要那种安全感吗?如果你有很多冲突,你为什么不简单地增加表格的大小?

将总冲突减少到可接受的水平

很多冲突的可能性真的很小(通过一个很好的实现来保持表不密集)并且您已经保护了算法免受恶意输入(因为攻击者不知道如何滥用密钥)。对于现实生活中的应用,这已经比“可接受的水平”要好得多。

【讨论】:

  • 如果在两个通信应用程序的核心使用相同的代码,或者如果一个应用程序发现它突然需要重新处理过去落入给定哈希桶的所有内容,您可能会遇到一些病态情况年。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2010-10-12
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 2018-01-01
相关资源
最近更新 更多