算法图解之散列表

一、前言:

前面已经学习了两种数据结构:数组和链表

如果你是商店老板,面对顾客对商品的价格的询问,你肯定希望找一个服务员可以马上回答出价格,但服务员要想记住所有商品价格的可能性很小。

而你如果去使用数组存储包含两项内容的元素,然后按照商品名称排好序,那么你如果使用二分法去查找,那也得O(log n)时间,你想要的是O(1),而散列函数这时候就可以起作用了。

二、散列函数

散列函数就是无论你给它什么数据,它都还你一个数字。

散列函数也必须满足一些要求:
它必须是一致的,就是你如果输入Mike得到的是98,纳闷每次输入Mike得到的都是98。

你如果学习过python数据类型中的字典的话就很好理解,因为Python提供的散列表实现就是字典,所以你可以使用函数dist来创建散列表。

三、应用

你如果使用散列表去创建一个电话本,所以先创建一个散列表(字典):

book={}

那么就需要先添加人名和号码:

book["Mike"]=123456 
book["John"]=121212

然而添加时如何防止重复添加呢?这里get()函数派上用途了:

x=book.get("Mike")

如果Mike在散列表中就会返回True否则返回None

四、冲突与性能

假如你有一个10个位置的数组,当你把第一元素存储到散列表中时,分配给你的是第一个位置,当以把第二个元素存储到散列表中时,他分配给你的是第五个位置,可是当你如果添加第三个元素时,它又把第一个位置分配给你了,此时就出现冲突

解决方法中最简单的便是在同一个位置存储一个链表,可是如果绝大部分的元素都存储到同一个位置,这时候读取速度就会变慢,因为链表读取速度必须一个一个读取,如果这个元素在链表末尾,你就需要从头读取到尾(链表只能顺序访问)。

此时就需要计算填装因子,填装因子的计算很容易:

散列表包含的元素数/位置总数

散列表使用数组来存储数据,因此你需要计算数组中被占用的位置数。例如,下述散列表的
填装因子为2/5,即0.4。算法图解之散列表_第1张图片

填装因子大于1意味着商品数量超过了数组的位置数。一旦填装因子开始增大,你就需要在散列表中添加位置,这被称为调整长度。

算法图解之散列表_第2张图片

这个新散列表的填装因子为3/8,比原来低多了!填装因子越低,发生冲突的可能性越小,散列表的性能越高

一个不错的经验规则是:一旦填装因子大于0.7,就调整散列表的长度。

你可能在想,调整散列表长度的工作需要很长时间!你说得没错,调整长度的开销很大,因
此你不会希望频繁地这样做。

但平均而言,即便考虑到调整长度所需的时间,散列表操作所需的时间也为O(1)

你可能感兴趣的:(算法图解)