【问题标题】:Distinction between a data structure's members being stored by hash value and by index [closed]按哈希值和索引存储的数据结构成员之间的区别[关闭]
【发布时间】:2020-01-08 00:15:11
【问题描述】:

来自Picking the right data structure in Swift

就像我们在“Swift 中的集合的力量”中看到的那样,集合相对于数组的一大优势是插入和删除总是可以在恒定 (O(1)) 时间内执行,因为成员按哈希值存储,而不是按索引存储。

如果一个数据结构的成员是按哈希值而不是按索引存储的,这意味着什么?

【问题讨论】:

  • 你有关于Array和Hash map区别的背景知识吗?

标签: data-structures hash computer-science


【解决方案1】:

您实际上是在问 Array 和 Hash map/table/set 之间有什么区别。这是计算机科学“数据结构”课程的一部分,我相信您可以通过谷歌搜索每个课程的高级概述。强烈推荐:)

简而言之: 您可以将数组想象成一个带有单元格的长架子,其中每个单元格都有序列号(也称为索引):

数组:[dog][cat][mouse][fox]...
其中狗在#0 单元格,猫在#1 单元格,依此类推。

现在,您可以在数组中使用单元格index 检索对象,例如“给我单元格#1 的内容”。但是为了找出你的数组中是否有一个“鼠标”——你必须遍历所有的单元格。 (低效)

集合(又名哈希图)使用另一个索引存储对象 - “哈希码”,这是一种计算每个给定对象的一些伪唯一数字的函数(无需详细说明)。因此 cat 和 mouse 将具有唯一的哈希码,现在对于 Set 来说,找出 Set 中是否有“鼠标”非常有效。

【讨论】:

    【解决方案2】:

    数组被分配为单个的大内存块,并且条目由它们的索引访问。条目的顺序是固定的,除了它们在数组中的位置之外,它们不需要有特定的标识。

    其他更复杂的数据结构允许存储使用某种键标识和访问的对象。 (哈希表、集合、字典……)我们称这些“键控集合”。有些对象有一个自然键,例如“SocialSecurityNumber”,但是如果需要密钥并且数据对象中没有明显的候选字段,该怎么办?

    散列是一种技术,它旨在派生一个“相当独特的身份”以与一个对象相关联。将其视为将数字映射到(任意)数据。

    • 尽管有一些“标准哈希技术”,但这仍然是一个不断发展的领域 - 涉及一些有趣的数学。
    • 散列的用途包括安全散列(检测和防止故意篡改数据)、错误检测以及 - 在这种情况下 - 键控(或散列)数据访问。
    • 非安全散列算法应尽可能快,但优化速度可能涉及与映射要求的“相当独特”部分的权衡(而安全散列不可避免地 - 有时是故意的 - 更慢且贵)
    • 散列不能(永远)保证给定的散列值对于一个对象是唯一的,因此必须注意尽量减少“冲突”的发生并优化当它们发生时如何处理它们。当您认为数据必须被视为“任意”时,这本身就是一个困难的主题 - 要么看起来是随机的,要么包含序列/模式和/或重复。

    话虽如此,假设我们有一个“好的”散列函数,我们可以 - 至少在原则上 - 将任意对象存储在键控集合中。

    重要注意事项

    1. 数组提供极快的顺序和随机访问(按索引),而插入、删除和增长操作很慢。
    2. 键控集合具有您所引用的优势,即提供极快的插入和删除,但它们本质上是细粒度的,并引入了内存碎片等复杂性(内存管理是一种开销,增加的复杂性意味着增加的成本)。
    3. 当开始发生冲突时,性能会迅速下降。
    4. 没有免费的午餐,计算哈希相对昂贵(与简单地使用索引值或存储键相比)。
    5. “自然键”和索引没有的哈希有一个特定的缺点,即它们不提供自然排序/序列。 (按照哈希值顺序处理对象,就等​​于随机处理。)

    选择适合其预期用途的数据结构始终很重要(但这就是您引用的链接的全部内容;-)

    【讨论】:

      猜你喜欢
      • 2021-04-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 2010-11-11
      • 2017-10-17
      • 2022-08-03
      相关资源
      最近更新 更多