- 哈希表这种数据结构可以使数据的查询效率得到提升。哈希表存储的是由键(key)和值(value)组成的数据。比如每个人的性别作为数据存储,键为人名,值为对应的性别。
- 假设将数据存储在6个箱子里面(长度为6的数组)。比如查询Ally的性别,因为不知道Ally的数据存储在哪个箱子,所以只能从头开始查询。这个操作叫做“线性查找”。一般来说,我们可以把键当成数据的标识符,把值当成数据的内容。
1、数据的存储
使用哈希函数(hash)计算Joe的值,就是字符串“Joe”的哈希值。得到的结果是4928。将得到的哈希值除以数组的长度5,求得余数。Mod计算的结果是3。所以将Joe的数据存进数组的3号箱子。重复这样的操作把其他数据也放到数组中。
如果mod的余数一样,如何解决冲突?
- 可以利用链表在已有的数据后面插入新数据来进行解决冲突,这种方法是“链地址法”。存储完毕所有数据以后,哈希表就制作完成了。
- 需要注意,如果数组的空间太小,使用哈希表的时候容易发生冲突,线性查找的使用频率也会更高。同样,如果数组的空间太大,就会出现很多空箱子,造成内存的浪费。因此,给数组设定合适的空间非常重要。
- 除了“链地址法”还有一种应用比较多的解决冲突的方法是“开放地址法”。这种方法是当冲突发生了,立刻计算出一个候补地址(数组上的位置)并将数据存进去。如果还有冲突,便继续计算下一个候补地址,直到有空地址为止。可以通过多次使用哈希函数或“线性探测法”等方法计算候补地址。
2、数据的查询
假如查询Dan的性别,首先需要先算出Dan键的哈希值,然后对其进行mod运算。最后得到的结果是4,于是可以知道Dan是放在4号箱子里面。查看4号箱子发现其中的数据的键与Dan一致,于是便取出对应的值。由此可以知道Dan的性别是男。
如果想要查询Ally呢?先用Ally对应的哈希值进行mod运算,得到结果是3。但是3号箱子的数据是Joe不是Ally,所以此时需要对Joe所在的链表进行线性查找。于是可以找到Ally的数据,取出对应的值,便知道了Ally的性别是女。
3、优点
哈希表中,我们能应用哈希函数进行快速访问到数组中的目标数据。如果发生哈希冲突,就使用链表进行存储。这样不管数据量多少,都能应付。因为哈希表在数据存储上的灵活性和数据查找上的高效性,编程语言的关联数组等会经常用到它。