LRU Cache的原理和python的实现

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的实现)