[笔记]《算法图解》第五章 散列表
散列函数
- 散列函数是这样的函数,即无论你给它什么数据,它都还你一个数字。散列函数“将输入映射到数字”。
- 散列函数要求
它必须是一致的。
例如,假设你输入apple时得到的是4,那么每次输入apple时,得到的都必须为4
它应将不同的输入映射到不同的数字。
例如,如果一个散列函数不管输入是什么都返回1,它就不是好的散列函数。最理想的情况是,将不同的输入映射到不同的数字。
- 散列函数和数组创建了一种被称为散列表(hash table)的数据结构。
- 散列表适合用于
- 模拟映射关系;
- 防止重复;
- 缓存/记住数据,以免服务器再通过处理来生成它们。
- 经验教训
- 散列函数很重要。
前面的散列函数将所有的键都映射到一个位置,而最理想的情况是,散列函数将键均匀地映射到散列表的不同位置。
如果散列表存储的链表很长,散列表的速度将急剧下降。然而,如果使用的散列函数很好,这些链表就不会很长!
好的散列函数很少导致冲突。
平均情况下,散列表的查找(获取给定索引处的值)速度与数组一样快,而插入和删除速度与链表一样快,因此它兼具两者的优点!但在最糟情况下,散列表的各种操作的速度都很慢。
因此,在使用散列表时,避开最糟情况至关重要。为此,需要避免冲突。
而要避免冲突,需要有:- 较低的填装因子;
- 良好的散列函数。
- 散列函数很重要。
缓存
- 缓存的优点
- 用户能够更快地看到网页.
就像你记住了月球与地球之间的距离时一样。下次你侄女再问你时,你就不用再使用Google搜索,立刻就可以告诉她答案。 - 需要做的工作更少。
- 用户能够更快地看到网页.
- 缓存是一种常用的加速方式,所有大型网站都使用缓存,而缓存的数据则存储在散列表中!
代码实现
- dict创建散列表
# 你可使用函数 dict 来创建散列表。
>>> book = dict()
# 创建散列表 book 后,在其中添加一些商品的价格。一个苹果的价格为67美分
>>> book["apple"] = 0.67
>>> book["milk"] = 1.49
# 牛奶的价格为1.49美元
>>> book["avocado"] = 1.49
>>> print book
{'avocado': 1.49, 'apple': 0.67, 'milk': 1.49}
# 非常简单!我们来查询鳄梨的价格。
>>> print book["avocado"]
1.49
- 创建缓存
cache = {}
def get_page(url):
if cache.get(url):
return cache[url]
# 返回缓存的数据
else:
data = get_data_from_server(url)
cache[url] = d
小结
- 你可以结合散列函数和数组来创建散列表。
- 冲突很糟糕,你应使用可以最大限度减少冲突的散列函数。
- 散列表的查找、插入和删除速度都非常快。
- 散列表适合用于模拟映射关系。
- 一旦填装因子超过0.7,就该调整散列表的长度。
- 散列表可用于缓存数据(例如,在Web服务器上)
- 散列表非常适合用于防止重复