14.散列表(下)

1.用散列表+链表的方式,在复杂度为O(1)里实现LRU:

LRU(Least Recently Used):维护一个固定大小的链表,如果缓存中存在当前元素,则删除并把它加入链表尾部。如果不存在,1)如果缓存已满(已达到链表最大长度),则删除头节点(最近最少用到的数据优先删除),然后把它加入尾节点;2)如果未满,则直接加入尾结点。

1.1 一个缓存系统主要包含以下三个操作:

  • 往缓存中添加一个数据

  • 从缓存中删除一个数据

  • 在缓存中查找一个数据

    如果只是使用链表,复杂度为O(n).如果将散列表和链表两种数据结合使用,可以将上面三个的复杂度都降低为O(1)

在这里插入图片描述

  1. 查找一个数据:通过散列表,足够均匀,基本上可以忽略拉链的遍历次数,复杂度为O(1)
  2. 删除一个数据:由于使用了了双向链表,可以通过prev节点在O(1)里找到上一个节点,复杂度为O(1),但是对于拉链,如果使用单链表,需要遍历当前链表上的节点,不过也可以基本忽略。如果拉链使用双向链表,则也可以在O(1)里完成操作
  3. 添加一个元素:如果元素在链表中,则先删除,然后加入尾结点,复杂度为O(1);如果不在,1)缓存已满,则先删除头结点,然后加入尾结点,复杂度为O(1) , 2)缓存未满,直接加入尾结点

2.总结

​ 散列表支持非常高效的数据插入、删除、查找操作,但是散列表中的数据都是通过散列函数打乱之后无规律存储的。也就是说,它无法支持按照某种顺序快速地遍历数据。如果希望按照顺序遍历散列表中的数据,那我们需要将散列表中的数据copy到数组中,然后排序,再遍历。

​ 因为散列表是动态数据结构,不停地有数据插入、删除所以当我们希望按顺序遍历散列表中的数据的时候,都需要先排序,那么效率势必会很低。为了解决这个问题,我们将散列表和链表(或者调表)结合一起使用。

3.思考

​ 如果使用散列表+单链表的实现方式:

  1. 查找一个数据:通过散列表,足够均匀,基本上可以忽略拉链的遍历次数,复杂度为O(1)
  2. 删除一个数据:由于使用了单向链表,只能循环找到上一个节点,复杂度为O(n),但是对于拉链,如果使用单链表,需要遍历当前链表上的节点,不过也可以基本忽略。如果拉链使用双向链表,则也可以在O(1)里完成操作, 总复杂度为O(n)
  3. 添加一个元素:如果元素在链表中,则先删除,然后加入尾结点,即先删除头结点,然后插入到尾结点,复杂度为O(1);如果不在,1)缓存已满,则先删除头结点,然后加入尾结点,复杂度为O(1) , 2)缓存未满,直接加入尾结点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值