学了哈希表的算法:字符串哈希,模拟散列表。
但似乎对哈希表的认识还不够清楚,哈希表是个什么东西?什么场景适合用哈希表?
今天我们用理论和比喻相结合让哈希表的展现出真实面目,揭开抽象概念下的神秘。
什么是哈希表?
这里有一个解释:
散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
这个解释不太懂也没事,里面有一些特殊名词,给大家解释一下,那么对于哈希表就更理解了一点。
首先我们明确:
1,哈希表是一个数据结构。
2,哈希表本质是一个数组,通过对数组进行一些处理得到哈希表。
我们知道数据结构有很多种,每一种都有各自的特点,哈希表既然也是一种数据结构,那它有什么特点呢?根据上面的解释,我们大致能知道:可以根据一个key值来直接访问数据,因此查找速度快。
我们举一个很常见的例子:
当你想从一个电话本里找到一个人的电话号码,你很可能会从头到尾挨个看过去,如果这个人恰好在最后一页,那么你前面就做了很多的无用功了。
但是,如果按照人名分个类,比如按照首字母来排序,按ABCD......去查找人名不是快很多了嘛😁
这样子就能很快找到张三的电话号码,省去了很多无用功,查找速度自然就快了。
而这其实就是一种哈希表。这里我们用到了一种分类的方法——按首字母分类的方法。
散列函数
那么“方法”在我们的哈希表里有一个特殊的名词叫做——散列函数(也叫做映射函数)
我们把张三这个名字通过一些处理加工得到首字母Z的方法其实就是一种映射函数
张三这个名字数据通过映射函数得到了Z这个键值,通过键值就可以快速找到张三所在的位置,以及他的电话号码。
上面说到哈希表的本质是数组,那么如果再来了一个张四,那么Z字母下就有两个人了。
那么该怎么存储呢,这里我们就要讲到哈希表的实现。
实现哈希表我们可以采用两种方法:
1、数组+链表
2、数组+二叉树
我们以第一个为例解释一下
这样我们就能存储下Z字母下的多个人名,而这里Z下的两个人名就是所谓的哈希冲突。
哈希冲突
许多数据通过映射函数映射到不同的键值上,但是由于数据往往比较多,难免出现不同数据映射到同一个键值上的情况发生,也就是哈希冲突。
解决这个冲突可以用拉链法(我之前的文章有讲解过,也就是上图数组和链表的结合),或者是开放寻址法。
也不用处理冲突的情况,也就是通过取一些经验值,使得数据发生哈希冲突的概率很小很小(我之前讲到的字符串哈希就是这个应用)
哈希表的核心
核心就是映射函数,好的映射函数,可以减少冲突,提高查找效率。
好了,今天的哈希表的认识就到这里了。