微信公众号:云计算通俗讲义
持续输出技术干货,欢迎关注!
通过本文你将了解:
- 哈希表背景
- 哈希表概述特点
- 哈希算法分类
- 哈希表实现原理
- 哈希表有优缺点
- 散列函数
- 冲突解决
- 哈希表代码实现
- 哈希表应用场景
01 背景
假设某大学有10000名同学,每个人的学号是由学院-年级-班级-序号组成,例如学号为16140113表示是16系,14级1班的13号。为了快速查找到13号的成绩信息,可以建立一张表,但是不能用学号作为下标,学号的数值实在太大。因此将学号除以1100100取余,即得到编号作为该表的下标,那么,要查找学号为16140113的成绩的时候,只要直接访问表下标为13的数据即可。这就能够在O(1)时间复杂度内完成成绩查找。实际上这里就用到了散列的思想。
02 概述
理想散列表(哈希表)是一个包含关键字的具有固定大小的数组,它能够以常数时间执行插入,删除和查找操作。
每个关键字被映射到0到数组大小N-1范围,并且放到合适的位置,这个映射规则就叫散列函数/哈希(hash)函数。
理想情况下,两个不同的关键字映射到不同的单元,然而由于数组单元有限,关键字范围可能远超数组单元,因此就会出现两个关键字散列到同一个值得时候,这就是散列冲突。
注:那些元素间任何排序信息的操作将不会得到有效的支持,因此,诸如FindMin、FindMax以及线性时间将排过序的整个表进行打印的操作都是散列所不支持的。
03 分类
3.1 静态哈希
特点:拥有固定slot(桶)数
如果数据是固定不变的,那么静态哈希较为实用。由于这些键固定不变,而且可以提前为静态哈希算法所获知,因此目录中的主要页面数量也会保持稳定。
3.2 动态哈希
动态哈希表通常是在发生冲突后slot数量翻倍增长,而增长后毕竟哈希函数也变了,所以还要把旧slot里的元素重新放置。这种简单的动态哈希(dynamic hash)算法便是SGI版的STL中hash_map的实现。
如果数据不固定,那么静态哈希的性能就比较低。这种类型的数据适合采用动态哈希技术来处理。
04 原理
假设有一个大小为7的表,现在,要将13,18,19,50,20散列到表中。主要操作步骤:
1、选择散列函数,例如使用hash(x)=x%7作为散列函数;
2、计算数据散列值,并放到合适的位置。
具体如下:
计算13 % 7得到6,因此将13放到下标为6的位置:
![308b31d72054420b0bcac62848608d59.png](https://i-blog.csdnimg.cn/blog_migrate/c34162ebdfb930dc29e1bd3363e009a5.jpeg)
计算18 % 7得到4,因此将18放到下标为4的位置:
![132636f155f092b90b2e13e21cb55d72.png](https://i-blog.csdnimg.cn/blog_migrate/17004f8309097bd8ed024f4fad011d46.jpeg)
计算19 % 7得到5,因此将19放到下标为5的位置: