美文网首页Pythoner集中营Python小学生python
LRU Cache的原理和python的实现

LRU Cache的原理和python的实现

作者: NeilShao | 来源:发表于2018-10-18 23:56 被阅读4次

    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 OrderedDict
    
    class 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')])
    
    

    相关文章

      网友评论

        本文标题:LRU Cache的原理和python的实现

        本文链接:https://www.haomeiwen.com/subject/ytpezftx.html