Python中的LFU缓存


假设我们想设计和实现一种用于最低使用频率(LFU)缓存系统的数据结构。它应该支持以下操作:

  • get(key) – 如果键存在于缓存中,则用于获取键的值;否则返回-1。

  • put(key, value) – 用于设置或插入值,前提是键不存在。

当缓存达到最大容量时,在插入新元素之前,应使最低使用频率的元素失效。

因此,如果LFUCache初始化容量为2,并调用这些方法:cache.put(1, 1); cache.put(2, 2); cache.get(1); cache.put(3, 3); cache.get(2); cache.put(4, 4); cache.get(1); cache.get(3); cache.get(4); 那么输出将分别为1,-1,1,-1,4。

为了解决这个问题,我们将遵循以下步骤:

  • 初始化程序将接收容量值

  • remain := capacity

  • least_freq := 1

  • node_for_freq := 一个映射,用于根据插入顺序保存数据

  • node_for_key := 一个新的映射

  • 定义一个函数_update()。它将接收key和value

  • x, freq := node_for_key[key]

  • 从node_for_freq[freq]中删除对应于key的元素

  • 如果node_for_freq[least_freq]的大小为0,则

    • least_freq := least_freq + 1

  • node_for_freq[freq+1, key] := value, freq+1

  • node_for_key[key] := value, freq+1

  • 定义一个函数get()。它将接收key

  • 如果key不在node_for_key中,则

    • 返回-1

  • value := node_for_key[key, 0]

  • _update(key, value)

  • 返回value

  • 定义一个函数put()。它将接收key和value

    • 如果key在node_for_key中,则

      • _update(key, value)

    • 否则,

      • node_for_key[key] := value,1

      • node_for_freq[1, key] := value,1

      • 如果remain为0,则

        • removed := 按FIFO顺序从node_for_freq[least_freq]中删除一个元素

        • 从node_for_key中删除对应于removed[0]的元素

      • 否则,

        • remain := remain - 1

      • least_freq := 1

示例

让我们来看下面的实现,以便更好地理解:

在线演示

import collections
class LFUCache:
   def __init__(self, capacity):
      self.remain = capacity
      self.least_freq = 1
      self.node_for_freq = collections.defaultdict(collections.OrderedDict)
      self.node_for_key = dict()
   def _update(self, key, value):
      _, freq = self.node_for_key[key]
      self.node_for_freq[freq].pop(key)
      if len(self.node_for_freq[self.least_freq]) == 0:
         self.least_freq += 1
      self.node_for_freq[freq+1][key] = (value, freq+1)
      self.node_for_key[key] = (value, freq+1)
   def get(self, key):
      if key not in self.node_for_key:
         return -1
      value = self.node_for_key[key][0]
      self._update(key, value)
      return value
   def put(self, key, value):
      if key in self.node_for_key:
         self._update(key, value)
      else:
         self.node_for_key[key] = (value,1)
         self.node_for_freq[1][key] = (value,1)
         if self.remain == 0:
            removed = self.node_for_freq[self.least_freq].popitem(last=False)
            self.node_for_key.pop(removed[0])
         else:
            self.remain -= 1
            self.least_freq = 1
cache = LFUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1))
cache.put(3, 3)
print(cache.get(2))
cache.put(4, 4)
print(cache.get(1))
print(cache.get(3))
print(cache.get(4))

输入

cache.put(1, 1)
cache.put(2, 2)
cache.get(1)
cache.put(3, 3)
cache.get(2)
cache.put(4, 4)
cache.get(1)
cache.get(3)
cache.get(4)

Learn Python in-depth with real-world projects through our Python certification course. Enroll and become a certified expert to boost your career.

输出

1
-1
1
-1
4

更新于:2020年7月21日

2K+浏览量

启动你的职业生涯

通过完成课程获得认证

开始学习
广告