散列函数
先了解什么是散列函数,即:将输入映射到数字。
它满足一些要求:
- 它必须是一致的,即输入A得到的是1,那么每次输入A时,得到的都必须是1.如果不是这样,散列表将毫无用处。
- 它应将不同的输入映射到不同的数字。例如,如果一个散列函数不管输入是什么都返回1,它就不是一个好的散列函数。最理想的情况就是,将不同的输入映射到不同的数字。
散列函数将输入映射位数字的用处:首先创建一个数组,数组中的数据存储位置都是有索引的(从0开始),而返回的就是数组的索引,那么输出就是该索引中的值了。
散列表
散列表由键和值组成
例如以下关于超市商品价格的代码,键是商品名,值为商品价格。
supermarket = dict()
supermarket["apple"] = 2
supermarket["milk"] = 3
supermarket["pen"] = 2
supermarket["chocolate"] = 7
print(supermarket)
不过,理想的散列函数是很少的,一般都会存在冲突,即好几个输入对应于一个索引,但是这与一对一的关系是冲突的,而且添加记录的时候后一个数据会覆盖前一个已近记录好了的数据。例如,apple和banan的价格都存储在一个位置,假设apple的价格先存储,那么banana的价格会覆盖掉apple的价格。最简单的办法:如果两个键映射到了同一个位置,就在这个位置存储一个链表。
注意的是
- 散列函数很重要;
- 如果散列表存储的链表很长,散列表的速度将急剧下降。
散列表的应用
一、查找
例如要创建一个电话簿,需将姓名映射到电话号码,需要一下功能
- 添加联系人及其电话号码
- 通过输入联系人来获得电话号码
非常适合使用散列表来实现
1创建映射
phone_book = dict()
# phone_book = {}
2添加联系人
phone_book["Fire alarm"] = 119
phone_book["emergency"] = 110
print(phone_book)
3查询
print(phone_book["emergency"])
二、防止重复
#voted = {}
voted = dict()
def check_voter(name):
if voted.get(name):
print("kick them out!")
else:
voted[name] = True
print("let them vote!")
测试结果为
三、用作缓存
小结:
适合散列表的情况:
- 模拟映射关系;
- 防止重复;
- 缓存/记住数据,以免服务器再通过处理来生成它们。