LRU的map+双链表实现(Go描述)

面云账户时候问了LRU,具体实现的方式是map+双链表。Set和Get的时间复杂度都是O(1)。完整写一遍复习一下, 仅作记录

Copy
/** * @Author: lzw5399 * @Date: 2021/5/20 22:28 * @Desc: 基于map和双链表实现的LRU算法 */ package main import "sync" func main() { lru := NewLRUCache(3) lru.Set(1, 233) lru.Set(2, 666) lru.Set(3, 777) lru.Set(5, 888) lru.Get(2) } // LRUCache type LRUCache struct { capacity int cache map[int]*LinkedNode head *LinkedNode tail *LinkedNode sync.RWMutex } type LinkedNode struct { key, value int prev, next *LinkedNode } func NewLRUCache(capacity int) *LRUCache { return &LRUCache{ capacity: capacity, cache: make(map[int]*LinkedNode, capacity), head: nil, tail: nil, RWMutex: sync.RWMutex{}, } } // - key是否已存在 // - 已存在, 将该节点移动到链表头部 // - 未存在, 判断cap是否已满 // - 满 // - 移除链表尾的节点 // - 新的node放入链表头 // - 新的node放入cache的map中 // - 未满 // - 新的node放入链表头 // - 新的node放入cache的map中 func (l *LRUCache) Set(key int, value int) { l.RLock() node, exist := l.cache[key] l.RUnlock() if exist { l.moveToHead(node) return } node = &LinkedNode{ key: key, value: value, } l.Lock() defer l.Unlock() if l.capacity == len(l.cache) { removedNode := l.removeTail() delete(l.cache, removedNode.key) } l.addToHead(node) l.cache[key] = node } // - 从map中获取是否存在 // - 不存在 // - 返回-1 // - 存在 // - 移到链表头部 // - 并返回具体的值 func (l *LRUCache) Get(key int) int { l.RLock() node, exist := l.cache[key] l.RUnlock() if !exist { return -1 } l.moveToHead(node) return node.value } func (l *LRUCache) moveToHead(node *LinkedNode) { l.removeNode(node) l.addToHead(node) } func (l *LRUCache) removeTail() *LinkedNode { return l.removeNode(l.tail) } func (l *LRUCache) removeNode(node *LinkedNode) *LinkedNode { // 头节点 if node.prev == nil { l.head = node.next node.next.prev = nil return node } // 尾节点 if node.next == nil { l.tail = node.prev node.prev.next = nil return node } // 中间节点 node.prev.next = node.next node.next.prev = node.prev return node } func (l *LRUCache) addToHead(node *LinkedNode) { if l.head == nil { l.tail = node } else { l.head.prev = node } node.prev = nil node.next = l.head l.head = node }
posted @   宝树呐  阅读(212)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示