检查值时,Set如何实际在内部工作?

时间:2019-04-18 16:28:34

标签: hash set big-o notation

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

我已经多次使用它们,建议使用它们来存储唯一值并快速访问它们。用Big-O表示,每次访问Set时,其时间和复杂度为O(1)。如果Set包含数千个项目,怎么可能?即使项目是唯一的。

为了在Set中找到一个项目,它仍然必须扫描每个唯一的项目,在Big-O中,时间和复杂度均为O(n)。我在这里想念什么吗?

预先感谢您的帮助!最彻底的答案会得到投票!

1 个答案:

答案 0 :(得分:1)

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

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

存储element的过程如下:

  1. hash计算element
  2. 表中的index被计算为表中hash的{​​{1}}的余数。
  3. 如果已经计算出length处的插槽,则将应用某些策略来解决冲突

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

步骤2假设(在大多数情况下)表的长度是素数的数字(也使用cryptographic的幂)

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

  • 依次扫描该表2次,直到j上的插槽可用,或者
  • 该元素被添加到在给定的index + j存储桶)上发生冲突的元素集合中

此外,如果没有足够的空插槽(这会增加发生冲突的可能性),则会放大表格并index(因为rehashed已更改)。

有了足够的可用时隙和索引机制的相当随机的分布,在modulo中找到所需时隙的可能性非常高。当然,如果有太多的元素冲突,则平均复杂度不再O(1),但是可以通过不断增长的策略(+ O(1))来减轻。

检索类似。为了检查rehash是否属于集合,需要计算其elementhash,并将modulo与目标槽的内容进行比较。如果比较失败,搜索将在存储桶中线性进行。

在没有element且增加bucket的情况下,删除元素会有些困难,但是您会明白的。

如果您真的想了解所有这些工作,请继续进行调试,并调试任何Smalltalk方言中indexes的基本操作。保证有很多乐趣。