【问题标题】:Hash table O(1) amortized or O(1) average amortized?哈希表 O(1) 摊销还是 O(1) 平均摊销?
【发布时间】:2018-02-13 02:17:17
【问题描述】:

这个问题可能看起来有点迂腐,但我一直在尝试更深入地研究摊销分析,并且对于为什么插入哈希表是 O(1) 摊销有点困惑。(注意:我不是在谈论表加倍,我明白)

使用此定义,“摊销分析给出了最坏情况下每个操作的平均性能(随着时间的推移)。”似乎 N 次插入哈希表的最坏情况会导致每个操作发生冲突。我相信,当负载平衡保持在低水平时,通用散列保证以 1/m 的速率发生冲突,但是理论上是否仍然有可能为每个插入发生冲突?

从技术上讲,哈希表插入的平均摊销分析似乎是 O(1)。

编辑:您可以假设哈希表使用基本链接,其中元素放置在相应链接列表的末尾。我的问题的真正实质是对概率算法的摊销分析。

编辑 2: 我在快速排序上找到了this 的帖子, “此外,摊销运行时间和预期运行时间之间存在微妙但重要的差异。随机枢轴快速排序需要 O(n log n) 预期运行时间,但其最坏情况下的运行时间为 Θ(n^2)。这意味着快速排序花费 (n^2) 美元的可能性很小,但随着 n 变大,这种情况发生的概率接近于零。”我想这可能回答了我的问题。

【问题讨论】:

  • 哈希表的实现方式有很多种,实现方式的选择会有所不同。例如,如果哈希桶是(未排序的)链表,那么插入总是 O(1),假设你从不调整表的大小。
  • 不同的实现会以不同的方式处理冲突。例如,碰撞可能会进入下一个可用点,或者它可能存储在同一点但通过链表,或类似但通过树。请详细说明如何处理碰撞,以便我们有一个固定的目标进行分析。
  • 严格来说,根据问题中给出的“摊销”定义,您是绝对正确的。因此,如果哈希算法通过链表处理冲突,则其“摊销”复杂度将为O(n)。尽管该术语通常与您给出的“平均摊销”的含义一起使用。

标签: hash big-o hashtable


【解决方案1】:

理论上,每次插入都会发生冲突,但这意味着您的哈希函数性能不佳,无法在键的“桶”中隔开值。理论上完美的散列函数总是将一个新值放入一个新的桶中,这样每个键都会引用它自己的桶。 (我假设一个链式哈希表并将链式字段称为“桶”,就像我被教导的那样)。理论上最坏情况的函数会将所有键放入同一个桶中,从而导致该桶中长度为 N 的链。

摊销背后的想法是,给定一个相当好的散列函数,您应该以线性时间结束插入,因为插入的次数 > O(1) 将大大低于插入次数很简单并且 O(1)。这并不是说插入没有任何计算(哈希函数仍然需要计算,并且在某些特殊情况下,哈希函数可能比仅查看列表更繁重)。

归根结底,这给我们带来了 big-O 中的一个重要概念,即在计算时间复杂度时,您需要查看最常执行的操作。在这种情况下,这是插入一个不与另一个哈希冲突的值。

【讨论】:

    猜你喜欢
    • 2021-04-03
    • 2012-12-03
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    相关资源
    最近更新 更多