美文网首页
算法8:LRU Cache

算法8:LRU Cache

作者: HYIndex | 来源:发表于2021-03-17 10:21 被阅读0次

    LeetCode No.146 LRU缓存机制

    LRU(Least Recent Used)策略:优先淘汰最近最少使用的数据,常用于缓存淘汰机制,如Linux系统的内存淘汰、Redis的缓存淘汰等。

    基于哈希表和双向链表实现LRU

    核心思路是,利用双向链表存储键值对,哈希表存储键在链表中对应的节点指针,如下图所示


    这样的好处是使访问和更新操作时间复杂度都在O(1)。

    PUT操作

    • 判断哈希表中key是否已存在,如果存在为修改操作:
      1. 将链表节点修改为新的键值对
      2. 将节点移到头部
    • 如果不存在为新增操作,此时如果容量已满,需要淘汰数据
      1. 取出链表尾节点,删除哈希表中对应key
      2. 删除链表尾节点
      3. 在链表头部添加新的节点
      4. 将新的链表头节点加到哈希表
    • 如果容量没有满,直接添加节点,执行上述步骤3、4即可

    GET操作

    • 判断哈希表中key是否存在,如果存在将节点移动到链表头部,返回对应的值
    • 如果不存在直接返回nil值

    Go语言实现

    使用Go内建map类型和container包的list(双向链表)

    import (
        "container/list"
    )
    
    type Pair struct {
        key int
        val int
    }
    
    type LRUCache struct {
        cap int
        list *list.List
        kv map[int]*list.Element
    }
    
    
    func Constructor(capacity int) LRUCache {
        return LRUCache{
            cap: capacity,
            list: list.New(),
            kv: make(map[int]*list.Element),
        }
    }
    
    
    func (this *LRUCache) Get(key int) int {
        if v, ok := this.kv[key]; ok == true {
            this.list.MoveToFront(v)
            return v.Value.(Pair).val
        } else {
            return -1
        }
    }
    
    
    func (this *LRUCache) Put(key int, value int)  {
        if elem, ok := this.kv[key]; ok == true {
            elem.Value = Pair{key: key, val: value}
            this.list.MoveToFront(elem)
            return
        }
        if this.list.Len() >= this.cap {
            delete(this.kv, this.list.Back().Value.(Pair).key)
            this.list.Remove(this.list.Back())
        }
        this.list.PushFront(Pair{key: key, val: value})
        this.kv[key] = this.list.Front()
    }
    

    相关文章

      网友评论

          本文标题:算法8:LRU Cache

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