【发布时间】:2021-12-23 14:58:29
【问题描述】:
为什么哈希使数据访问(键,值)比原始对更快?
换句话说,我们到底为什么需要哈希函数 h()? h() 的范围似乎仍然只是另一个整数。
【问题讨论】:
-
你所说的“比原来的对更快”是什么意思?就像只是将值放入数组中,键是索引?
-
@ConnorRobetorye,是的,为什么还要麻烦将密钥散列到另一个数字?
标签: hash
为什么哈希使数据访问(键,值)比原始对更快?
换句话说,我们到底为什么需要哈希函数 h()? h() 的范围似乎仍然只是另一个整数。
【问题讨论】:
标签: hash
您是正确的,访问/访问存储在哈希表中的数据并不比访问存储在数组中的相同数据快(假设您已经知道值存储在数组中的索引/键)。事实上,访问哈希表中的数据稍微慢一些,因为使用数组时,您只是使用索引作为访问数据的键,而对于散列键/值对,您必须计算键的索引使用 h() 在哈希表中,然后才能访问它。
但是,哈希表主要不是用于快速访问给定键的数据值(尽管在这方面它们仍然非常快):它们用于快速在给定键的情况下搜索数据值:即使在存储的键/值动态变化时也能保持快速访问。此外,哈希表允许您使用任意类型的值作为键,而数组将您限制为整数(索引)键。即使您只需要整数键,哈希表在存储键/值对方面通常比数组更节省空间。
因此,例如,如果您已经知道所需值存储在数组 A 中的索引 n 处,并且它将始终位于索引 n 处,或者您只想访问任何值在索引n 处,不管它是什么,那就太好了——只需使用一个数组并在每次需要该值时调用A[n]。
当您不知道是否存储了某个键/值,或者您知道该值已存储但您没有准确跟踪其位置时,就会出现散列。散列可以让您计算要查找的键的索引并检查该索引以在恒定时间内检索值,但是对于未散列的数组,您必须进行完整的线性搜索才能尝试找到一个值,如果你没有明确地跟踪它的索引。
这是因为普通数组不太适合存储键/值对以进行快速查找。您可以用于查找的键仅限于数组的索引(或从不同类型的键到整数的一些整数映射,这基本上已经是一个哈希函数),一般来说,当您存储一些值的集合时在动态变化的数组中,您不会知道存储每个值的确切索引,这意味着如果不维护与键的单独映射,就无法基于键快速(恒定时间)查找值数组索引本身比咬紧牙关并在每次查找时进行线性搜索更昂贵。
即使您要为其存储值的键集没有变化并且所有键都是整数,这意味着理论上您可以通过将键 1 存储在索引 1 处、键 2 存储在索引处来将键/值存储在一个简单的数组中2,...因此,您不需要哈希函数或从键到数组索引的单独映射,以便在动态变化的键/值对集中进行查找以提高效率:即使这一切都是真的,使用数组直接基于索引而不是散列索引实现键/值查找仍然可能会浪费大量空间。这是因为一个简单的基于数组的键/值查找需要空间来存储它可以存储的每个潜在键。因为每个键都有自己的索引,所以没有散列的数组需要与它存储的 键范围成比例的空间。但是,哈希函数将键的范围缩小到底层哈希表的大小,它本身将是当前存储的 number 个键的恒定倍数。这意味着散列方法通常会更有效,因为几乎没有浪费的空间,与存储稀疏但范围广泛的未散列键相比,浪费的空间可能要少几个数量级。
因此,基本上,如果您想通过键快速检索数据,那么像通过数组索引那样直接使用整数键不会节省时间或空间——除了非常特殊的情况,按键快速检索将需要一个辅助数据结构,如哈希表 + 哈希函数或树。
【讨论】: