数据结构四——散列表(下)

文章出处:极客时间《数据结构和算法之美》-作者:王争。该系列文章是本人的学习笔记。

7 散列表+链表的应用

很多情况下散列表会和链表一起使用。散列表可以通过key查找value。链表可以按照value进行排序。这样就能通过value查找key,也可以通过查找value的区间范围查找key。

7.1 LRU 缓存淘汰算法

基本的LRU
 单纯的LRU是维护了一个访问时间从大到小的有序链表。因为缓存大小有限,当超过缓存的时候,需要删除表头。
 当要缓存一个数据的时候,先查找数据在链表中是否存在。如果存在,则删除,插入到表尾。如果不存在,则看空间是否充足。空间充足,直接插入到表尾;如果空间不足,则删除表头,插入到表尾。
LRU支持的操作有:
 1 插入数据
 2 删除数据
 3 查找数据
 这三个操作都涉及查找操作。链表的查找操作时间复杂度是O(n)。散列表+链表就可以将查找操作变为O(1)。
 在这里插入图片描述
 一个双向链表+散列表。每个节点=数据+前驱指针+后继指针+hnext指针。hnext是为了把节点串在散列表中。前驱指针、后继指针是为了形成一个双向列表。
 查找数据的过程。我们通过散列表查找数据,时间复杂度O(1)。找到之后把它移动到双向链表的尾部。
 删除数据的过程。我们通过散列表查找数据节点,利用前驱后继指针删除这个节点。
 插入数据的过程。需要先查找这个节点是不是存在。存在,移动到双向链表的尾部。不存在需要插入到散列表对应的槽位,和双向链表的尾部。如果超出缓存空间,则把双向链表头部元素删除。
 所有查询的操作通过散列表完成。这三个操作都可以在O(1)时间内完成。

7.2 Redis有序集合

有序集合中每个对象有两个重要属性key和value。
有序集合需要支持的操作有:
1 添加一个成员对象。
2 按照key删除成员对象。
3 按照key查找成员对象。
4 按照value区间查找对象。
5 按照value从大到小排序对象。
 在跳表,我们可以实现按照value排序数据。散列表可以按照key组织数据。即可以在O(1)实现上述5种操作。
 Redist还可以按照排名查找对象。这个功能在以后讲。

7.3 Java LinkedHashMap

Java的LinkedHashMap实际是一个LRU缓存的实现版本。是一个散列表+双向列表。遍历Map中的元素,遍历的顺序是按照访问时间从小到大输出。

7.4 散列表+链表结构特点

散列表:支持高效地插入、删除、查找操作。
双向链表:按照某种顺序遍历数据。
两者结合在一起就可以实现按照某种顺序遍历散列表中的数据

7.5 应用

假设猎聘网有 10 万名猎头,每个猎头都可以通过做任务(比如发布职位)来积累积分,然后通过积分来下载简历。假设你是猎聘网的一名工程师,如何在内存中存储这 10 万个猎头 ID 和积分信息,让它能够支持这样几个操作:
根据猎头的 ID 快速查找、删除、更新这个猎头的积分信息;
查找积分在某个区间的猎头 ID 列表;
查找按照积分从小到大排名在第 x 位到第 y 位之间的猎头 ID 列表。
 以积分排序构建一个跳表,按照ID做key构建一个散列表。
 在散列表中根据ID查找、删除、插入积分信息。
 在跳表查找积分区间内的ID。
 最后一个操作以后实现,目前做不到。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值