恭喜发现宝藏!微信搜索公众号【TechGuide】关注更多新鲜好文和互联网大厂的笔经面经。 作者@TechGuide【全网同名】 点赞再看,养成习惯,您动动手指对原创作者意义非凡🤝
引子为什么有哈希表?因为在很多场景下,对这种数据结构是由应用需求的,比如在编译阶段,需要形成对变量及其属性的有效管理,这样才能判断一些操作是否合法(比如数据是否重复定义,数据类型是否合法等),再比如一些应用设计字符串的比较,相比于数字比较,这种成本是增加的,那么是否可以把字符串转化为数字,再做处理呢?
这些问题都可以在学习散列表的过程中逐步解答。
正文 铺垫先复盘一下已知的查找方法: 这里给出一个非常有趣的实际例子,登录qq时,服务器是如何快速在庞大的用户群中找到你的信息并快速核对的呢? 如果用二分法这种静态查找的方法的话,可以得出,
所以适应这种场景下的数据结构无疑等待着一个高效且动态的(随时可以添加/删除记录的)数据结构,再引出之前,我们先探讨一下查找的本质,那就是根据对象找到他的位置,这样就有两种思路:
- 有序安排对象,可以是全序(数组等)或者半序(查找树)
- 直接”算出“对象的位置,引出散列
散列表基本工作: 但是复杂度与函数计算和冲突有关。
这里再引出一个哈希冲突的概念 有冲突怎么办呢?后来冲突的元素就没有位置了,直观想法是用二维数组,增加一个位置存放元素。但是这种缓解是有限的,如何有效解决呢?这就需要设计一个”好“的散列函数。一般满足下列条件:
-
直接定址法
-
除留余数法
-
数字分析法
比如身份证后几位比较随机
- 折叠法/平方取中法
如果关键词是字符又该如何处理呢?
- ASC码加和法
但是范围太窄,很多哈希冲突,可以改进:
以下是一段很巧妙的快速计算代码,可以研究下:
通常遇到冲突,常见思路有两种:
- 换个位置再存(开放地址法)
缺点是很容易连续冲突,不断试探位置,最后在冲突的地方越积累越多,最后造成冲突聚集现象。可以通过下图理解。
散列表的性能分析可以通过成功平均查找长度(即是比较次数且最后找到了)ASLs和不成功平均查找长度ASLu(即是比较次数且最后没找到)评价。
直观理解也能预期分布更均匀,观察下表一系列值存入哈希表的过程:
它的缺点是,可能空间不会充分利用,有些空间永远探测不到。但是他的优点是缓解了冲突聚集问题。
双散列探测法其中di为探测偏移量。
- 同一位置的冲突对象可以组织在同一个单链表中(链地址法)
把握住一个重点,适合哈希查找的问题都是需要高效查找的并且多是动态的。
1. 词频统计(利用哈希查找快速查找和插入) 实现代码如下: