学习散列表

回顾一下简单查找和二分查找

杂货店商品对应的价格举例:
简单查找就是拿出商品价目本,这个价目本并不是有序的,顾客问苹果多少钱,需要一个一个去查找某一个商品的价格,需要O(n)时间。
同样是一个价目本,但是按商品名称字母排序的,这样需要的时候更短为O(logn)。
二分查找和简单查找
但这样我还是觉得查找太慢,怎么办,这时候需要一名能记住所有商品价格的员工,这样一问评价价格便知,只需要O(1)。

从数据结构的角度来看
你可使用数组来实现记录商品价格的本子,的每个元素包含两项内容:商品名和价格。
数组记录商品
如果将这个数组按商品名排序,就可使用二分查找在其中查找商品的价格。这样查找价格的时间将为O(log n)。
然而,我希望查找商品价格的时间为O(1),这是散列函数的用武之地。

散列函数

无论你给散列函数什么数据,它都还你一个数字,专业点说:散列函数“将输入映射到数字”

特点:

  • 一致的,比如输入苹果得到的是4,之后的每一次输入苹果最后得到的都是4。
  • 不同的输入映射不同的数字。

简单实现商品价目本:
准备一个空列表,将苹果输入散列函数,输出4,那么列表的索引4就存苹果价格¥2.1,依次类存。。。行程价目本。
这样我们想知道商品名(苹果)价格,直接把苹果给散列函数,输出的就是价目表的索引4位置的价格(¥2.1)。

注意: 散列函数知道数组有多大,只返回有效的索引。如果数组包含5个元素,散列函数就不会
返回无效索引100。

散列表

复杂数据结构中,散列表可能是最有用的,也被称为散列映射、映射、字典和关联数组。散列表的速度很快!和数组一样快。
Python提供的散列表实现为字典,你可使用函数dict来创建散列表。

散列表的应用

将散列表用于查找
比如电话本

>>> phone_book = {}
>>> phone_book["小明"] = 8675309
>>> phone_book["火警"] = 119
>>> print phone_book["小明"] # 查找jenny的电话

比如DNS解析(DNS resolution):网址映射到ip地址
我想浏览www.baidu.com 需要先进行DNS解析成ip地址192.168.0.0(随便写的ip地址)然后再进行访问百度服务器。

防止重复
比如投票机制:已经投过票的不能再投了

voted = {} # 散列表查找元素非常快
def check_voter(name):
	if voted.get(name):
		print "kick them out!"
	else:
		voted[name] = True
		print "let them vote!"

如果将已投票者的姓名存储在列表中,这个函数的速度终将变得非常慢,因为它必须使用简单查找搜索整个列表。

作为缓存
你登录了Facebook,你看到的所有内容都是为你定制的。你每次访问facebook.com,其服务器都需考虑你感兴趣的是什么内容。但如果你没有登录,看到的将是登录页面。每个人看到的登录页面都相同。 Facebook被反复要求做同样的事情:“当我注销时,请向我显示主页。”有鉴于此,它不让服务器去生成主页,而是将主页存储起来,并在需要时将其直接发送给用户。

  • 用户能够更快地看到网页,网站已经记住了用户的访问频次或喜好等行为。
  • Facebook需要做的工作更少。

Facebook不仅缓存主页,还缓存About页面、 Contact页面等众多其他的页面。因此,它需要将页面URL映射到页面数据。
也就是一个字典中key是url,value是网页数据data

cache = {}
def get_page(url):
	if cache.get(url): 
		return cache[url]
	else:
		data = get_data_from_server(url) # 访问服务器处理并返回数据填充到散列表
		cache[url] = data
		return data

仅当URL不在缓存中时,你才让服务器做些处理,并将处理生成的数据存储到缓存中,再返回它。这样,当下次有人请求该URL时,你就可以直接发送缓存中的数据,而不用再让服务器进行处理了。

这里总结一下,散列表适合用于:

  • 模拟映射关系;
  • 防止重复;
  • 缓存/记住数据,以免服务器再通过处理来生成它们。

tips:本篇文章参考算法图解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值