LRU Cache的原理和python的实现
LRU的原理
LRU(Least Recently Used)即最近最少使用。 操作系统中一种内存管理的页面置换算法,主要用于找出内存中较久时间没有使用的内存块,将其移出内存从而为新数据提供空间。此算法的前提是认为:当一个数据被访问的越频繁,则这个数据在未来被访问的概率就越高。
LRU算法其实就是按照使用顺序将元素倒叙排列,在有限的存储空间中,若空间满时,删除最后的元素(即最久没有使用的元素)。若想实现高效实现这个算法,使get和set都能O(1)的效率,需要一个有序的字典。
LRU的Python实现(库函数版)
首先实现一个双向链表, 没啥好说的,简单实现一下:
class Node: def __init__(self, data, _pre=None, _next=None): self.data = data self._pre = _pre self._next = _next def __str__(self): return str(self.data)class DoublyLink: def __init__(self): self.tail = None self.head = None self.size = 0 def insert(self, data): if isinstance(data, Node): tmp_node = data else: tmp_node = Node(data) if self.size == 0: self.tail = tmp_node self.head = self.tail else: self.head._pre = tmp_node tmp_node._next = self.head self.head = tmp_node self.size += 1 return tmp_node def remove(self, node): if node == self.head: self.head._next._pre = None self.head = self.head._next elif node == self.tail: self.tail._pre._next = None self.tail = self.tail._pre else: node._pre._next = node._next node._next._pre = node._pre self.size -= 1 def __str__(self): str_text = "" cur_node = self.head while cur_node != None: str_text += cur_node.data + " " cur_node = cur_node._next return str_text
实现LRU算法
插入数据时:若空间满了,则删除链表尾部元素,在进行插入
查询数据时:先把数据删除,再重新插入数据,保证了元素的顺序是按照访问顺序排列
class LRUCache: def __init__(self, size): self.size = size self.hash_map = dict() self.link = DoublyLink() def set(self, key, value): if self.size == self.link.size: self.link.remove(self.link.tail) if key in self.hash_map: self.link.remove(self.hash_map.get(key)) tmp_node = self.link.insert(value) self.hash_map.__setitem__(key, tmp_node) def get(self, key): tmp_node = self.hash_map.get(key) self.link.remove(tmp_node) self.link.insert(tmp_node) return tmp_node.data
测试代码
r = LRUCache(3) r.set("1", "1") r.set("2", "2") r.set("3", "3") print r.link r.get("1") print r.link r.set("4", "4") print r.link>> 3 2 1>> 1 3 2>> 4 1 3
LRU的Python实现(OrderedDict)
OrderedDict的本质就是一个有序的dict,其实现也是通过一个dict+双向链表
from collections import OrderedDictclass LRUCache: def __init__(self, size): self.size = size self.linked_map = OrderedDict() def set(self, key, value): if key in self.linked_map: self.linked_map.pop(key) if self.size == len(self.linked_map): self.linked_map.popitem(last=False) self.linked_map.update({key: value}) def get(self, key): value = self.linked_map.get(key) self.linked_map.pop(key) self.linked_map.update({key: value}) return value
测试代码
r = LRUCache(3) r.set("1", "1") r.set("2", "2") r.set("3", "3") print r.linked_map r.get("1") print r.linked_map r.set("4", "4") print r.linked_map>> OrderedDict([('1', '1'), ('2', '2'), ('3', '3')])>> OrderedDict([('2', '2'), ('3', '3'), ('1', '1')])>> OrderedDict([('3', '3'), ('1', '1'), ('4', '4')])
作者:NeilShao
链接:https://www.jianshu.com/p/e41ec08e4aa6