python(9): 实现LRU

LRU全称是Least Recently Used

题目:设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能

  • set(key, value):将记录(key, value)插入该结构
  • get(key):返回key对应的value值

[要求]

  1. set和get方法的时间复杂度为O(1)
  2. 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
  3. 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。

实现:

1.采用字典+双向链表组合实现

2.字典key为存数据时的key;字典value为链表节点node

3.每次get/set操作都将key对应的节点移到链表头部

4.set新数据时,链表长度已满则去掉尾部节点

# -*- coding: UTF-8 -*-
class Lur:
    def __init__(self, k):
        # write code here
        '''
        读取删除值用hash
        key的活跃度用双向链表,hash表记录key所在链表中的node(val,pro,next)
        ?对象转为字符串
        '''
        if not isinstance(k, int) or k <= 0:
            raise Exception("长度须为大于0的整数")
        self.max = k  # 链表的最大长度
        self.length = 0  # 链表的当前长度
        self.data = {}  # key为索引,val为链表节点
        self.link_head = None  # 双向链表的头
        self.link_tail = None  # 双向链表的尾
    
    def set(self, key, value):
        
        if not self.data and self.length < self.max:
            now = Node(None, None, key,value)
            self.data[key] = now
            self.link_head = now
            self.link_tail = now
            self.length = self.length + 1
            return
        if self.length < self.max:
            hed = self.link_head
            now = Node(None, hed, key,value)
            self.data[key] = now
            self.link_head = now
            hed.p_pro = now
            self.length = self.length + 1
            return
        if self.length >= self.max:
            hed = self.link_head
            now = Node(None, hed, key,value)
            self.data[key] = now
            self.link_head = now
            hed.p_pro = now
            now_tail = self.link_tail
            self.link_tail = self.link_tail.p_pro
            del self.data[now_tail.key]
            
            self.link_tail.p_next = None
            self.length = self.length
            return
    
    def get(self, key):
        now = self.data[key]
        pro = now.p_pro
        n = now.p_next
        hed = self.link_head
        if not pro:  #当前节点为头部
            return self.data[key].val
        if not n:   #当前节点为尾部
            self.link_tail = self.link_tail.p_pro

        self.link_head = now
        now.p_next = hed
        hed.p_pro=now
        return self.data[key].val
 


class Node():
    def __init__(self, p_pro, p_next, key,val):
        self.p_pro = p_pro
        self.p_next = p_next
        self.val = val
        self.key = key

if __name__ == '__main__':
    mylen = 3       #测试定义长度为3的缓存
    mylur = Lur(mylen)
    for i in range(mylen+2):   #超出缓存长度进行试验
        key = 'key'+str(i)
        val = 'val-'+str(i)
        mylur.set(key,val)
        now = mylur.link_head
        
        print("---head------")           #从头部一次打印当前数据
        while now:  
            print(now.val)
            now = now.p_next
        print("=====tail=======")        #从尾部依次打印当前数据
        now = mylur.link_tail
        while now:
            print(now.val)
            now = now.p_pro


==》》
---head------
val-0
=====tail=======
val-0
---head------
val-1
val-0
=====tail=======
val-0
val-1
---head------
val-2
val-1
val-0
=====tail=======
val-0
val-1
val-2
---head------
val-3
val-2
val-1
=====tail=======
val-1
val-2
val-3
---head------
val-4
val-3
val-2
=====tail=======
val-2
val-3
val-4

有其他实现方案或对此代码有疑问或改进意见请留言提出

你可能感兴趣的:(算法,Python,算法)