是什么:
散列表又名哈希表、hash表
Java中对应的数据结构有hashmap
Python中对应的数据结构叫做 字典
它是一种基于数组,借助散列函数进行扩展的数据结构,它利用数组支持下标随机访问的特性,使得我们寻找元素时,利用映射就可以知道元素的位置,查找的时间复杂度为O(1)(粗略的看)。
假如要将 牛奶的价格存入数组
牛奶 ----> 散列函数运算 -----> 表中的某一个位置------>在位置存储价格
当查找时,输入牛奶,得到数组位置,取出价格。
散列表功能:
1.模拟映射关系
2.防止重复
3.……
什么是散列冲突:
简单来说,就是不同键映射到不同数组位置,但是有几率映射到同一个位置。
好的散列函数就是将数据均匀的散列到各个位置。
解决散列冲突的方法:
1.开放寻址法open addressing
如果要插入的位置已经重复,那就从那个位置开始寻找新的位置,再插入
(1)线性探测Linear Probing 随着位置的减少,探测的时间增大,最坏情况达到o(n)
(2)二次探测Quadratic probing 步长变成 线性探测 的平方
(3)双重散列Double hashing 使用 一组 散列函数得到位置。
2.链表法 chaining
常用,相比更简单
原理:
当数组可用位置逐渐减少,冲突的几率就会增大,假如A位置已经放入了一个元素,那么就不能存放第二个元素了,所以数组在A位置上放置链表,当查找元素在A位置时,再索引链表中是否有这个元素,这样就暂时解决了冲突问题,但随着链表元素的增加,查询速度会变慢,那么整体效率又会急剧下降O(n)。
而java中的hashmap在之前就是使用的链表法,jdk1.8加入了红黑树,当链表达到一定长度转为红黑树。
哈希表的性能:
如何让散列冲突少,让数据均匀的散列到各个位置上,散列函数就很重要了,这也是衡量散列性能的重要依据
1.较低的装填因子load factor 已有数据个数/散列表长度
2.良好的散列函数
比如:SHA函数,MD5,SHA,CRC
一般的当装填因子大于0.7就需要扩充散列表了,调整长度
而数组的调整长度就是数组复制,会花费很长的时间,不需要频繁的调整,就需要刚开始的时候根据情景设定初始大小和装填因子
插播阿里面试题:
这是我春招阿里一面的hashmap相关面试题
1.讲讲hashmap
2.hashmap的组成
3.hashmap为什么要使用数组加链表,有什么好处?
4.你说的是jdk 1.8hashmap有什么变化
5.什么时候链表转化为红黑树
6.为什么要改为红黑树,了解红黑树吗?
7.讲讲红黑树的左旋和右旋
你说为啥后面没有了呢?因为到这里我就回答不出来了,面试官问其他方向知识了。
本参考资料:《算法图解》《数据结构与算法之美》——极客时间专栏