为什么哈希后数据访问变得更快

why data visit becomes quicker after hash

为什么hash使得数据访问(键,值)比原来的pair更快?

换句话说,我们到底为什么需要哈希函数 h()? h() 的范围似乎仍然只是另一个整数。

您是正确的,visiting/accessing 存储在散列 table 中的数据并不比访问存储在数组中的相同数据快(前提是您已经知道 index/key 的值存储在数组中)。事实上,访问散列 table 中的数据稍微慢一些,因为对于数组,您只是使用索引作为访问数据的键,而对于散列 key/value 对,您必须先使用 h() 计算散列 table 中的键索引,然后才能访问它。

但是,散列 table 的主要用途并不是因为它们可以根据密钥快速 访问 数据值(尽管它们在这方面仍然非常快): 它们用于快速 搜索 给定键的数据值:即使正在存储的 keys/values 正在动态变化,快速访问仍然存在。此外,散列 table 允许您使用任意类型的值作为键,而数组将您限制为整数(索引)键。即使您只需要整数键,散列 table 存储 key/value 对的效率通常比数组高得多 space。

因此,例如,如果您已经知道所需的值存储在数组 A 中的索引 n 处,并且它将始终位于索引 n 处,或者您只想访问索引 n 处的任何值,而不管它是什么,那就太好了——只需使用数组并在每次需要该值时调用 A[n]

当您不知道是否存储了一些 key/value,或者您知道该值已存储但您没有准确跟踪时,散列法就派上用场了在哪里。散列可以让您计算要查找的键的索引并检查该索引以在恒定时间内检索值,但是对于未散列的数组,您将必须进行完整的线性搜索以尝试找到一个值,如果您没有明确跟踪其索引。

这是因为原始数组不太适合存储 key/value 对以供快速查找。您可以用于查找的键仅限于数组的索引(或从不同类型的键到整数的一些整数映射,这基本上已经是一个哈希函数),而且,一般来说,当您存储一些值的集合时在动态变化的数组中,您不会知道每个值存储的确切索引,这意味着如果不维护与键的单独映射,则无法基于键快速(恒定时间)查找值数组索引本身比硬着头皮在每次查找时都进行线性搜索要昂贵。

即使您要为其存储值的键集没有改变并且所有键都是整数,这意味着理论上您可以通过将键 1 存储在索引 1 来将 keys/values 存储在一个简单的数组中,索引 2 处的键 2,...因此您不需要散列函数或从键到数组索引的单独映射,以便在动态变化的 key/value 对集合中进行高效查找:即使这一切确实如此,使用数组直接基于索引而不是散列索引来实现 key/value 查找仍然可能会浪费大量 space。这是因为一个简单的基于数组的 key/value 查找需要 space 它可以存储的每个潜在键。因为每个键都有自己的索引,所以没有散列的数组需要 space 与其存储的 键范围 成比例。然而,哈希函数将键的范围缩小到底层哈希的大小 table,它本身将是当前存储的键的 数量 的常数倍数。这意味着散列方法通常会更有效,因为几乎没有浪费 space,与存储稀疏但范围广泛的未散列键相比,浪费可能少几个数量级 space。

所以基本上,如果你想通过键快速检索数据,直接使用整数键就不会是时间或 space 效率,就像你可能通过数组索引一样——除了非常专业在某些情况下,通过键快速检索将需要辅助数据结构,如散列 table + 散列函数或树。