java 最少使用(lru)置换算法_数据结构和算法LRU缓存

20b1a2e52febef5f261a8e027760929a.gif

74e96f630545feeae8ebe98355d7a2d0.png

黑客技术 点击右侧关注,了解黑客的世界! 24d847637a23603521256a41b909be4b.png

d14bd092caeed4ba85c7f82e5a4a2a0b.png

Linux编程 点击右侧关注,免费入门到精通! 24d847637a23603521256a41b909be4b.png

LRU, 内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据

缓存使用策略有三种

1、FIFO(先进先出队列)

2、LFU - Least frequently Used (最少使用)
如果一段数据在最近一段时间被访问的次数很少, 那么在将来被访问的次数也很少

3、LRU - Least Recently Used(最近最少使用)

如果一段数据在最近的一段时间没有被访问到, 那么之后被访问到的概率很小

方案一: O(n)

维护一个有序单链表. 尾部是最近使用的, 头部是最早使用的. 当有一个新数据被访问时, 遍历该链表, 有以下情况

  1. 如果已经被缓存在链表中, 得到这个节点, 删除后移动到最尾部

  2. 如果没有被缓存

如果链表未满, 直接加入尾部

如果链表满了, 删除头部, 把新节点加入尾部

如果直接使用单链表实现的话, 查找操作时间复杂度是O(n), 所以通常还会再借助散列表来提高查找速度. 但是在空间已满的时候需要删除最早使用的数据, 所以还需要保证使用顺序

方案二: O(1)

实现有序的散列表: 借助散列表和双向链表实现, 散列表用来快速定位, 双向链表用来存储数据

实现

使用OrderDict实现

 1# coding:utf-823from collections import OrderedDict456class LRUCache(object):7    """
 8    借助OrderedDict的有序性实现, 内部使用了双向链表
 9    """1011    def __init__(self, max_length: int = 5):12        self.max_length = max_length13        self.o_dict = OrderedDict()1415    def get(self, key):16        """
17        如果找到的话移动到尾部
18        :param key:
19        :return:
20        """21        value = self.o_dict.get(key)22        if value:23            self.o_dict.move_to_end(key)24        return value2526    def put(self, key, value):27        if key in self.o_dict:28            self.o_dict.move_to_end(key)29        else:30            if len(self.o_dict) >= self.max_length:31                # 弹出最先插入的元素32                self.o_dict.popitem(last=False)33        self.o_dict[key] = value343536if __name__ == "__main__":37    lru = LRUCache(max_length=3)38    lru.put(1, "a")39    lru.put(2, "b")40    lru.put(3, "c")41    assert lru.o_dict == OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])42    lru.get(2)43    assert lru.o_dict == OrderedDict([(1, 'a'), (3, 'c'), (2, 'b')])44    lru.put(4, "d")45    assert lru.o_dict == OrderedDict([(3, 'c'), (2, 'b'), (4, "d")])

使用dict和list实现

 1# coding:utf-823from collections import deque456class LRUCache(object):7    def __init__(self, max_length: int = 5):8        self.max_length = max_length9        self.cache = dict()10        self.keys = deque()1112    def get(self, key):13        if key in self.cache:14            value = self.cache[key]15            self.keys.remove(key)16            self.keys.append(key)17        else:18            value = None19        return value2021    def put(self, key, value):22        if key in self.cache:23            self.keys.remove(key)24            self.keys.append(key)25        else:26            if len(self.keys) >= self.max_length:27                self.keys.popleft()28                self.keys.append(key)29            else:30                self.keys.append(key)31        self.cache[key] = value323334if __name__ == "__main__":35    lru = LRUCache(max_length=3)36    lru.put(1, "a")37    lru.put(2, "b")38    lru.put(3, "c")39    assert lru.keys == deque([1, 2, 3])40    lru.get(2)41    assert lru.keys == deque([1, 3, 2])42    lru.put(4, "d")43    assert lru.keys == deque([3, 2, 4])

lru_cache

可以使用python3.7中自带的lru缓存模块

 1from functools import lru_cache234@lru_cache(maxsize=32)5def fibs(n: int):6    if n == 0:7        return 08    if n == 1:9        return 110    return fibs(n-1) + fibs(n-2)111213if __name__ == '__main__':14    print(fibs(10))

应用

Redis的LRU策略

Java的LinkedHashMap

使用散列表和双向链表实现

总结

数组利用索引可以快速定位, 但是缺陷是需要内存连续

链表优势是内存可以不连续, 但是查找慢

散列表和链表/跳表混合使用是为了结合数组和链表的优势

资料

数据结构和算法之美-王争

【无门槛免费领】

535G超强程序员编程

0基础从入门到精通自学视频教程!

5a37be0517c70b65b39008c8ecf6b32f.png

ee1c6ba59978a996f27bfbf67142e86c.png 60aacec19ec39f8f3182da0f43f60d78.png

7b5e7f28778614d0ef8be781c3c2dfd7.png 62a0a0daa6a59ff64a98d62716441dd2.png 49d2018d08ea0537f729880c15b7b098.png

2e1d863243eafcb7106c0598809ea597.png ee21db6e034a3089029fdb99b8ad118b.png f62f19866ddeb5429ed1a5b4097b6f22.png

f84d9e0261099ffc79f42e8b96bd2a82.png 7b5e7f28778614d0ef8be781c3c2dfd7.png 2e1d863243eafcb7106c0598809ea597.png

3aa827eab764ed7dd6df18da1cf647aa.png b0b2d195f78ef88331069550894742ab.png 581519bd7a239ddb9713924aa98ce498.png b52d04587f6ab81c2fbea5960a42b1dc.png

39786269bf49ec95d5e68dbf12f0c15b.png万水千山总是情,点个 “ 在看” 行不行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值