数组和链表在 LRU 缓存的实现

缓存机制

在计算机中,我们发明了缓存(cache)技术来对频繁热点使用的数据进行读取,以大大提高数据读取效率。缓存机制广泛应用于CPU、数据库和浏览器等软件设计中,它们可以将跟用户的交互体验产生质的飞跃。但是,用作缓存空间的硬件极其昂贵,一般软件能使用的缓存空间都很小。这样就需要数据结构与算法去提升缓存空间的合理利用率,我们通常将缓存的设计模式规定为最近最少使用策略 LRU (Least Recently Used)。

LRU 设计思路

  1. 如果此数据之前已经被缓存在数组或者链表中了,遍历得到这个数据所属位置,并将其从原来的位置删除,然后再插入到数组或者链表的首位;
  2. 如果未在数组和链表中发现此数据,则将此结点插入到数组和链表的头部;
  3. 数组和链表达到自身最大缓存容量,删除末尾的数据。

LRU 数组实现

import random


class LRUCache:

    def __init__(self, capacity: int = 10):
        self._capacity = capacity
        self._data = []

    def __len__(self):
        return len(self._data)

    def __repr__(self):
        return str(self._data)

    def is_exist(self, value: object) -> int:
        for index in range(0, len(self._data)):
            if self._data[index] == value:
                return index
        return -1

    def save(self, value):
        index = self.is_exist(value)
        if index != -1:
            self._data.insert(0, self._data.pop(index))
        else:
            if len(self) >= self._capacity:
                self._data.pop(len(self) - 1)
            self._data.insert(0, value)


if __name__ == '__main__':
    cache = LRUCache(5)
    for n in range(20):
        i = random.randint(0, 7)
        cache.save(i)
        print("cache.save(%d)" % i, cache)

终端输出的结果:

cache.save(2) [2]
cache.save(2) [2]
cache.save(2) [2]
cache.save(6) [6, 2]
cache.save(6) [6, 2]
cache.save(3) [3, 6, 2]
cache.save(7) [7, 3, 6, 2]
cache.save(4) [4, 7, 3, 6, 2]
cache.save(3) [3, 4, 7, 6, 2]
cache.save(3) [3, 4, 7, 6, 2]
cache.save(6) [6, 3, 4, 7, 2]
cache.save(0) [0, 6, 3, 4, 7, 2]
cache.save(5) [5, 0, 6, 3, 4, 7]
cache.save(7) [7, 5, 0, 6, 3, 4]
cache.save(6) [6, 7, 5, 0, 3, 4]
cache.save(2) [2, 6, 7, 5, 0, 3]
cache.save(7) [7, 2, 6, 5, 0, 3]
cache.save(3) [3, 7, 2, 6, 5, 0]
cache.save(5) [5, 3, 7, 2, 6, 0]
cache.save(4) [4, 5, 3, 7, 2, 6]

LRU 链表实现

import random


class ListNode(object):
    def __init__(self, value, next=None):
        self.value = value
        self.next = next


class LRUCache:
    def __init__(self, capacity: int = 10):
        self.capacity = capacity
        self.head = ListNode(None, None)
        self.length = 0

    def __len__(self):
        return self.length

    def __repr__(self):
        values = []
        pointer = self.head.next
        while pointer:
            values.append(str(pointer.value))
            pointer = pointer.next
        return '->'.join(values)

    def is_exist(self, value: object) -> object:
        pointer = self.head
        while pointer.next:
            if pointer.next.value == value:
                return pointer
            pointer = pointer.next
        return pointer

    def remove_tail(self):
        pointer = self.head
        prev = None
        while pointer.next:
            prev = pointer
            pointer = pointer.next
        prev.next = None
        self.length -= 1

    @staticmethod
    def insert_to_head(head, node):
        node.next = head.next
        head.next = node

    def save(self, value: object):
        prev = self.is_exist(value)
        if len(self) > 0 and prev.next is not None:
            dest = prev.next
            prev.next = dest.next
            self.insert_to_head(self.head, dest)
        else:
            if self.length >= self.capacity:
                self.remove_tail()
            self.insert_to_head(self.head, ListNode(value))
            self.length += 1


if __name__ == '__main__':
    cache = LRUCache(5)
    for _ in range(20):
        value = random.randint(0, 8)
        cache.save(value)
        print("cache.save(%d),length(%d)" % (value, len(cache)), cache)

终端输出的结果:

cache.save(0),length(1) 0
cache.save(1),length(2) 1->0
cache.save(3),length(3) 3->1->0
cache.save(0),length(3) 0->3->1
cache.save(4),length(4) 4->0->3->1
cache.save(4),length(4) 4->0->3->1
cache.save(0),length(4) 0->4->3->1
cache.save(1),length(4) 1->0->4->3
cache.save(5),length(5) 5->1->0->4->3
cache.save(7),length(5) 7->5->1->0->4
cache.save(0),length(5) 0->7->5->1->4
cache.save(6),length(5) 6->0->7->5->1
cache.save(7),length(5) 7->6->0->5->1
cache.save(3),length(5) 3->7->6->0->5
cache.save(8),length(5) 8->3->7->6->0
cache.save(1),length(5) 1->8->3->7->6
cache.save(0),length(5) 0->1->8->3->7
cache.save(6),length(5) 6->0->1->8->3
cache.save(8),length(5) 8->6->0->1->3
cache.save(3),length(5) 3->8->6->0->1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值