散列(在Ruby这样的语言中)是如何工作的;“在引擎盖下”吗;?

散列(在Ruby这样的语言中)是如何工作的;“在引擎盖下”吗;?,ruby,hash,hashmap,hashtable,Ruby,Hash,Hashmap,Hashtable,我已经读过很多关于哈希映射/表的书,并且可以理解哈希表本质上是一个有限大小的数组的概念。该函数可以使用模运算符确定数组中的哪个索引对应于特定键。如果发生冲突,则可以实现一个链表来存储所有冲突的值。这是我的新手理解,我希望有人能在Ruby哈希上下文中解释/纠正它。在Ruby中,您真正需要做的就是 hash = {} hash[key] = value 这将创建一个具有相应值的键。假设您只是将一组符号存储为键,将数字存储为值: hash[:a] = 1 hash[:b] = 2 ...

我已经读过很多关于哈希映射/表的书,并且可以理解哈希表本质上是一个有限大小的数组的概念。该函数可以使用模运算符确定数组中的哪个索引对应于特定键。如果发生冲突,则可以实现一个链表来存储所有冲突的值。这是我的新手理解,我希望有人能在Ruby哈希上下文中解释/纠正它。在Ruby中,您真正需要做的就是

hash = {}    
hash[key] = value
这将创建一个具有相应值的键。假设您只是将一组符号存储为键,将数字存储为值:

hash[:a] = 1
hash[:b] = 2
...

在数组和链表中存储值的过程中到底发生了什么?碰撞的例子是什么

如果你是这方面的铁杆人物,你可以直接查看实现。这就是散列最后使用的内容:

散列本身如下所示:


大多数情况下,diego在评论中提供的文章已经足够了

如果您对此非常关注,可以直接查看实现。这就是散列最后使用的内容:

散列本身如下所示:


大多数时候,diego在评论中提供的文章已经足够了

Ruby语言规范没有为
Hash
类规定任何特定的实现策略。只要他们遵守合同,每个实施都可以按照自己的意愿实施

例如,这里是Rubinius的实现,它是用Ruby编写的,非常容易理解:这是一个相当传统的哈希表。(关于这个实现还有一件很酷的事情需要注意,那就是它实际上和YARV一样快,这证明了Ruby代码可以和手工优化的C一样高效。)

RubIIUS还可替代地实现<代码>哈希< /Cuff>类,并用:(注意:此实现使用C++编写的三个VM原语)

您可以使用配置选项在这两种实现之间切换。因此,不同Ruby实现之间的
散列
实现不仅不同,而且在完全相同的Ruby实现的完全相同版本上运行的完全相同的程序之间也可能不同

在IronRuby中,Ruby的
Hash
类只是委托给.NET
System.Collections.Generic.Dictionary

在以前的版本中,它甚至没有委托,它只是一个子类:

Ruby语言规范没有为
Hash
类规定任何特定的实现策略。只要他们遵守合同,每个实施都可以按照自己的意愿实施

例如,这里是Rubinius的实现,它是用Ruby编写的,非常容易理解:这是一个相当传统的哈希表。(关于这个实现还有一件很酷的事情需要注意,那就是它实际上和YARV一样快,这证明了Ruby代码可以和手工优化的C一样高效。)

RubIIUS还可替代地实现<代码>哈希< /Cuff>类,并用:(注意:此实现使用C++编写的三个VM原语)

您可以使用配置选项在这两种实现之间切换。因此,不同Ruby实现之间的
散列
实现不仅不同,而且在完全相同的Ruby实现的完全相同版本上运行的完全相同的程序之间也可能不同

在IronRuby中,Ruby的
Hash
类只是委托给.NET
System.Collections.Generic.Dictionary

在以前的版本中,它甚至没有委托,它只是一个子类:

在ruby 2.4中,哈希表被移动到了开放寻址模型中,所以我将只描述哈希表结构是如何工作的,而不是它在2.4及更高版本中是如何实现的

假设我们将所有条目存储在一个数组中。当我们想要找到某样东西时,我们必须通过所有元素来匹配一个。如果我们有很多元素,并且使用哈希表可以通过计算该键的哈希函数直接转到具有所需值的单元格,那么这可能需要很长时间

哈希表以类似于数组的数据结构存储存储(BIN)组中的所有值

当我们添加一个新的键值对时,我们需要计算该对将被插入到哪个“存储”中,我们使用
.hash
方法(hash函数)来实现这一点。哈希函数的结果值是一个伪随机数,因为它总是为相同的值生成相同的数

粗略地说,
hash
返回指向内存位置的链接的等价物,其中 将存储当前对象。但是,对于字符串,计算是相对于值的

收到一个伪随机数后,我们必须计算存储键值对的“存储器”的数目

'a'。散列%16=>9
a键
16-存储量
9-存储编号

因此,在Ruby中,插入的工作方式如下:

  • 它使用内部哈希函数获取密钥的哈希值。
    :c.hash#=>2782

  • 在获得散列值后,借助模运算(2782%16),我们将获得保存键值对的存储编号
    :d.hash%16

  • 将键值添加到相应bin的链接列表中

  • 搜寻工作如下:

    搜索的工作方式完全相同:

  • 确定“散列”函数
  • 查找“存储”
  • 然后遍历列表并检索哈希元素
  • 在ruby中,每个bin的平均元素数是5。随着记录数量的增加,每个存储库中的元素密度将增加