【问题标题】:How does Set actually work internal when checking for values?Set 在检查值时如何在内部实际工作?
【发布时间】:2019-04-18 16:28:34
【问题描述】:

这是一个非常普遍的基于计算机科学的问题,但根据有关其工作原理的文献,这似乎并不直观。这是一个与语言无关的问题,但与 Set 数据类型在内部的工作方式有关。

我已经用过很多次了,建议使用它们来存储唯一值并快速访问它们。假设在 Big-O 表示法中,每次访问 Set 时,它的时间和复杂度都是 O(1)。如果 Set 可能包含数千个项目,这怎么可能?即使物品是独一无二的。

为了在 Set 中找到一个项目,它仍然需要扫描每一个唯一的项目,在 Big-O 中,时间和复杂度是 O(n)。我在这里有什么遗漏吗?

提前感谢您的帮助!最彻底的答案获得赞成票!

【问题讨论】:

    标签: hash set big-o notation


    【解决方案1】:

    Set 是一种更通用的对象,统称为HashedCollections。它们使用某种HashTable 来实际存储和检索它们的元素。

    给定任何element,这些表会为其计算一个整数值,命名为hash。有几种众所周知的技术可以定义元素与其hash 值之间的映射。有些是内在的,因为hash 不依赖于element 的属性,这些属性可能会改变,因此hash 在@ 的生命周期内保持不变987654330@。其他是外在的,从某种意义上说,它们可能取决于属性。但是,在后一种情况下,假设特定元素在从HashedCollection 引用时不会被修改(否则HashedCollection 必须是rehashed)。

    存储element 的过程如下:

    1. hash 是为 element 计算的。
    2. 表的index 计算为hash 以表的length 为模的余数。
    3. 如果如此计算的index 处的插槽已被占用,则应用某些策略来解决冲突

    第 1 步应该非常快(例如,hash 没有 cryptographic 强度)。

    第 2 步假设(在大多数情况下)表格的长度是一个素数数(也使用了2 的幂)

    第 3 步基本上可以通过两种不同的方式解决:

    • 依次扫描表j 次,直到index + j 的槽空闲,或者
    • 元素被添加到在给定index (bucket) 处发生碰撞的元素集​​合中

    另外,如果没有足够的空槽(这增加了碰撞的概率),表格被放大并rehashed(因为modulo改变了)。

    有了足够的空闲槽位和相当随机的索引机制分布,在O(1) 中找到所需槽位的概率非常高。当然,如果太多元素发生冲突,平均复杂度就不再是 O(1),但这应该被不断增长的政策所缓解(+ rehash)。

    检索类似。要检查element 是否属于集合,计算其hashmodulo,并将element 与目标槽的内容进行比较。如果比较失败,则在桶中线性搜索。

    当没有bucket 而增加indexes 时,删除元素会有些困难,但你明白了。

    如果您真的想看到所有这些在工作中,请继续在任何 Smalltalk 方言中调试 HashedCollections 的基本操作。保证有很多乐趣。

    【讨论】:

    • 非常感谢 Leandro 提供的非常详细且包罗万象的答案!我真的很感谢你花时间把它写下来!这是对幕后发生的事情的一些深刻见解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    • 2014-10-06
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 2022-11-29
    • 2021-12-27
    相关资源
    最近更新 更多