仅用于记录学习,欢迎批评指正,大神勿喷
系列文章目录
《算法图解》总结第 1 章:二分查找、大O表示法;
《算法图解》总结第 2 章:数组和链表,选择排序;
《算法图解》总结第 3 章:while循环、递归、栈;
《算法图解》总结第 4 章:分而治之、快速排序;
《算法图解》总结第 5 章:散列表;
《算法图解》总结第 6 章:广度优先搜索;
《算法图解》总结第 7 章:狄克斯特拉算法;
《算法图解》总结第 8 章:贪婪算法
《算法图解》总结第 9 章:动态规划
《算法图解》总结第 10 章:K最近邻算法
《算法图解》总结第 11 章:十种算法简介
散列表
散列表也被称为散列映射、映射、字典和关联数组。散列表是使用散列函数和数组共同创建的一种数据结构,可以使用散列函数来确定元素的存储位置。
散列函数需要满足两个要求:
(1)输入输出必须是一致的。
(2)散列函数应将不同的输入映射到不同的数字。
散列函数能准确指出元素的存储位置,原因有三:
(1)散列函数总是将同样的输入映射到相同的索引;
(2)散列函数将不同的输入映射到不同的索引;
(3)散列函数知道数组有多大,只返回有效的索引。
一、创建散列表
算法实现:Python
# 使用dict()函数创建散列表或者令book={},{}是字典专用符号
book = dict()
# 添加元素
book["apple"]=0.67
book["milk"]=1.49
book["avocado"]=1.49
# 输出散列表
print(book)
输出结果:
{'apple': 0.67, 'milk': 1.49, 'avocado': 1.49}
二、应用案例
1.将散列表用于查找
算法实现:Python
# 使用dict()函数创建散列表或者令book={},{}是字典专用符号
book = dict()
# 添加元素
book["apple"]=0.67
book["milk"]=1.49
book["avocado"]=1.49
# 输出散列表
print(book)
# 查询苹果价格
print(book["apple"])
输出结果:
{'apple': 0.67, 'milk': 1.49, 'avocado': 1.49}
0.67
2.防止重复
假设投票站限每人只能投一票 ,为避免重复,当有人来投票,将询问他的全名,与已投票名单做对比,若名字出现在名单中,说明已投票,不允许再投,否则允许其投票,并将其名单加入已投票名单中。
算法实现:Python
voted = {}
def check_voter(name):
# 与已投票者名单做对比
# 能得到名字,拒之门外
if voted.get(name):
print "kick them out!"
# 得不到名字,将其名字加入名单,让其投票
else:
voted[name] = True
print "let them vote!"
测试用例:
check_voter("tom")
check_voter("milk")
check_voter("tom")
输出结果:
let them vote!
let them vote!
kick them out!
3.缓存/记住数据
假设在网站工作,可对网页进行缓存(如使用Google搜索时,首页有之前使用过的一些网页),缓存是一种常用的加速方式,所有大型网站都使用缓存,而缓存的数据则存储在散列表里。
# 散列表用于缓存网页数据
cache = {}
def get_data(url):
# 若缓存有数据,直接返回数据
if cache.get(url):
return cache[url]
# 若没有缓存过,查找数据,缓存数据,返回数据
else:
data = get_data_from_serever(url)
cache[url]=data
return data
三、冲突
之前我们学到的是散列函数总是将不同的键映射到数组的不同位置,实际上,几乎不可能编写出这样的散列函数,有时会给两个键分配的位置相同,这种情况被称为冲突,处理冲突的方式:如果两个键映射到同一个位置,就在这个位置存储一个链表。
经验教训:
散列函数很重要:需要将键均匀地映射到列表的不同位置。
若散列表存储的链表很长,散列表的速度将会急速下降:若使用的散列函数很好,链表就不会长。
各种编程语言都提供了散列表实现,性能良好。