嗯,这样想吧。
如果您使用数组(一种简单的基于索引的数据结构),并用随机的东西填充它,那么当您用数据填充它时,查找特定条目将变得越来越昂贵,因为您基本上必须从一端朝向另一端,直到找到您想要的为止。
如果您想更快地访问数据,通常会求助于对数组进行排序并使用二分搜索。然而,这虽然提高了查找现有值的速度,但会导致插入新值的速度变慢,因为当您需要在中间插入元素时,您需要移动现有元素。
另一方面,哈希表有一个关联的函数,它接受一个条目,并将其简化为一个数字,即哈希键。然后,该数字将用作数组的索引,这就是存储条目的位置。
哈希表围绕一个数组,该数组最初是空的。空并不意味着长度为零,数组以一个大小开始,但数组中的所有元素都不包含任何内容。
每个元素都有两个属性:数据和标识数据的键。例如,美国邮政编码列表将是邮政编码 -> 名称关联类型。该函数减少了键,但不考虑数据。
因此,当您将某些内容插入哈希表时,该函数会将键减少为一个数字,该数字用作此(空)数组的索引,这就是您存储数据(包括键和关联数据)的位置。
然后,稍后,您想要找到您知道其密钥的特定条目,因此您通过相同的函数运行该密钥,获取其哈希密钥,然后转到哈希表中的该特定位置并检索那里的数据。
从理论上讲,将密钥减少为散列密钥(即该数字)的函数在计算上比线性搜索便宜得多。
典型的哈希表没有无限数量的可用于存储的元素,因此该数量通常会进一步减少到适合数组大小的索引。实现此目的的一种方法是简单地取索引与数组大小的模数。对于大小为 10 的数组,索引 0-9 将直接映射到下一个索引,索引 10-19 将再次向下映射到 0-9,依此类推。
某些键将被缩减为与哈希表中现有条目相同的索引。此时,将直接比较实际的键,并使用与比较键的数据类型相关的所有规则(例如,正常的字符串比较)。如果存在完全匹配,您要么忽略新数据(它已经存在),要么覆盖(替换该键的旧数据),要么添加它(多值哈希表)。如果没有匹配,这意味着虽然散列键相同,但实际键不同,您通常会找到一个新位置来存储该键+数据。
冲突解决有多种实现方式,最简单的一种是直接转到数组中的下一个空元素。但这个简单的解决方案还有其他问题,因此找到正确的解析算法对于哈希表来说也是一个很好的练习。
如果哈希表完全填满(或接近填满),哈希表也可以增长,这通常是通过创建新大小的新数组,并再次计算所有索引,并将项目放入新数组中的新数组来完成的。地点。
将密钥减少为数字的函数不会产生线性值,即。 “AAA”变为 1,然后“AAB”变为 2,因此哈希表不按任何典型值排序。
维基百科上也有一篇关于这个主题的很好的文章,here http://en.wikipedia.org/wiki/Hashtable.