1.文档阅读
https://time.geekbang.org/column/article/64233?//?18 | 散列表(上):Word文档中的单词拼写检查功能是如何实现的?
https://time.geekbang.org/column/article/64586?//?19 | 散列表(中):如何打造一个工业级水平的散列表?
https://time.geekbang.org/column/article/64858?//?20 | 散列表(下):为什么散列表和链表经常会一起使用?
https://time.geekbang.org/column/article/65312?//?21 | 哈希算法(上):如何防止数据库中的用户信息被脱库?
https://time.geekbang.org/column/article/67388?//?22 | 哈希算法(下):哈希算法在分布式系统中有哪些应用?
2.整理输出 1. 什么是哈希/散列表
散列表的英文叫“Hash Table”,我们平时也叫它“哈希表”或者“Hash 表”或者“散列表”。
散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。
2.? 案例解释 这里用一个例子来解释一下。
假如我们有 89 名选手参加学校运动会。为了方便记录成绩,每个选手胸前都会贴上自己的参赛号码。
这 89 名选手的编号依次是 1 到 89。现在我们希望编程实现这样一个功能,通过编号快速找到对应的选手信息。
你会怎么做呢? 我们可以把这 89 名选手的信息放在数组里。 编号为 1 的选手,我们放到数组中下标为 1 的位置;编号为 2 的选手,我们放到数组中下标为 2 的位置。 以此类推,编号为 k 的选手放到数组中下标为 k 的位置。 因为参赛编号跟数组下标一一对应,当我们需要查询参赛编号为 x 的选手的时候,我们只需要将下标为 x 的数组元素取出来就可以了,时间复杂度就是 O(1)。 这样按照编号查找选手信息,效率是不是很高?
实际上,这个例子已经用到了散列的思想。在这个例子里,参赛编号是自然数,并且与数组的下标形成一一映射,所以利用数组支持根据下标随机访问的时候,时间复杂度是 O(1) 这一特性,就可以实现快速查找编号对应的选手信息。
你可能要说了,这个例子中蕴含的散列思想还不够明显,那我来改造一下这个例子。
假设校长说,参赛编号不能设置得这么简单,要加上年级、班级这些更详细的信息,所以我们把编号的规则稍微修改了一下,用 6 位数字来表示。比如 051167,其中,前两位 05 表示年级,中间两位 11 表示班级,最后两位还是原来的编号 1 到 89。
这个时候我们该如何存储选手信息,才能够支持通过编号来快速查找选手信息呢? 思路还是跟前面类似。 尽管我们不能直接把编号作为数组下标,但我们可以截取参赛编号的后两位作为数组下标,来存取选手信息数据。当通过参赛编号查询选手信息的时候,我们用同样的方法,取参赛编号的后两位,作为数组下标,来读取数组中的数据。 这就是典型的散列思想。 其中,参赛选手的编号我们叫做键(key)或者关键字。我们用它来标识一个选手。 我们把参赛编号转化为数组下标的映射方法就叫作散列函数(或“Hash 函数”“哈希函数”), 而散列函数计算得到的值就叫作散列值(或“Hash 值”“哈希值”)。 通过这个例子,我们可以总结出这样的规律:
散列表用的就是数组支持按照下标随机访问的时候,时间复杂度是 O(1) 的特性。
我们通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。---> 写操作
当我们按照键值查询元素时,我们用同样的散列函数,将键值转化数组下标,从对应的数组下标的位置取数据。---> 读操作
3.?散列函数 Note
散列函数/哈希函数也可以认为哈希算法。
简单来说,解决过程思路就是算法,所以可以使用伪代码来表示;
具体实现就是程序来实现,当然就涉及到具体的编程语言
后续补充 ... |