算法图解之散列表

 1. 散列函数

散列函数就是将输入映射到数字。它必须知足两个条件:编程

  1. 输出必须一致,每次输出同一个key,都应获得一样的value。
  2. 将不一样的输入映射到不一样的数字,也就是不能输入什么key都获得一样的value。

以下图所示:数组

 

 

 

 

 

 

 散列函数能够准确的指出价格的存储位置,具体缘由以下:缓存

  • 散列函数老是将一样的输入映射到相同的索引。也就是说apple永远在第四个格子上
  • 散列函数将不一样的输入映射到不一样的索引。apple的索引为3,milk的索引为0
  • 散列函数知道数组有多大,只返回有效的索引

2. 应用案例

1. 手机内置的电话簿服务器

2. DNS解析,网址对应IP地址数据结构

3. 防止重复的一些场景,好比投票、领奖app

4. 缓存。好比说Facebook,它会把常常访问但又不须要动态传递数据的网页的数据储存在散列表中,好比about、注册、登录页面。当你访问Facebook的页面时,它首先检查散列表中是否存储了这些页面。这样能够大大下降服务器的压力,并且好的散列的运行时间是O(1),效率比去服务器拿数据要快得多。编程语言

 

3. 冲突

冲突就是给两个或多个键分配的位置相同。若是咱们按字母表,给散列函数26个位置,那么相同开头的字母就会占据同一个位置,以下图:函数

 

这会比一开始将全部元素储存到一个链表中还慢。性能

总结:

1. 要想办法把散列函数的键均匀地映射到散列表的不一样位置。3d

2.若是散列表存储的链表很长,散列表的速度将急剧降低。然而,若是使用的散列函数很 好,这些链表就不会很长!

3. 散列函数很重要,好的散列函数不多致使冲突。

 

4. 性能

在平均状况下,散列表的查找速度与数组同样快,而插入和删除速度与链表同样快,所以它兼具二者的优势。但在最糟状况下,散列表的各类操做的速度都很慢。

避免最糟糕状况的关键是避免冲突,这须要:

  1. 较低的填装因子
  2. 良好的散列函数

4.1 填装因子

填装因子 = 散列表包含的元素书 /  位置总数

 

一个经验规则是填装因子一旦大于0.7,就须要调整散列表的长度(resizing),一般将数组增加一倍,而后使用函数hash将全部的元素都插入到新的散列表中。

4.2 良好的散列函数

良好的散列函数让数组中的值呈均匀分布

 

糟糕的散列函数让值扎推,致使大量的冲突

 

 

5.总结

通常的编程语言都实现了散列列表,并且可以得到平均状况下的性能(包括Python):常量时间,O(1)

 

散列表是一种功能强大的数据结构,其操做速度快,还能让你以不一样的方式创建数据模型。你可能很快会发现本身常常在使用它。

  • 你能够结合散列函数和数组来建立散列表。
  • 冲突很糟糕,你应使用能够最大限度减小冲突的散列函数。
  • 散列表的查找、插入和删除速度都很是快。
  • 散列表适合用于模拟映射关系。
  • 一旦填装因子超过0.7,就该调整散列表的长度。
  • 散列表可用于缓存数据(例如,在Web服务器上)。
  • 散列表很是适合用于防止重复。
相关文章
相关标签/搜索