【剑指offer】LRU算法 [Go语言]

119 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

题目

题目很简洁,请你用go语言写一个LRU算法。

思考

其实我们可以借助go自带的list进行操作,因为这是一个很常见的置换算法。

AC Code

  • 定义cache的node块

这里包含了lru中所需的key和value。

type CacheNode struct {
   key, value interface{}
}
  • 定义LRU块
1. 这里用maxLen存储最大的大小,当超过这个大小就会淘汰最后一个元素。
2. ll作为一个双向列表进行前后块的链接
3. cache就是用来存储元素的集合
4. rwLock是因为我们用到了map所以要进行上锁
type LRUCache struct {
   maxLen int
   ll     *list.List
   Call   func(key interface{}, value interface{})
   cache  map[interface{}]*list.Element
   rwLock *sync.RWMutex
}
  • 新建一个lru块
func New(maxLen int) *LRUCache {
   return &LRUCache{
      maxLen: maxLen,
      ll:     list.New(),
      cache:  make(map[interface{}]*list.Element),
      rwLock: new(sync.RWMutex),
   }
}
  • 对lru进行元素的设置
func (l *LRUCache) Set(key,value interface{} ) error {
   if e, ok := l.cache[key]; ok { // 如果这个存在
      e.Value.(*CacheNode).value = value // 我们先用断言让这个CacheNode类型的value等于传入的value
      l.ll.MoveToFront(e) // 将这个元素移动到最前面
      return nil 
   }
   ele := l.ll.PushFront(&CacheNode{key: key, value: value}) 
   // 如果不存在,我们就需要进行cacheNode的创建,把这个元素推到最前面
   l.cache[key] = ele // 让这个key的value等于这个元素,存储数组
   if l.maxLen != 0 && l.ll.Len() > l.maxLen { // 如果大小超过了
      if e := l.ll.Back(); e != nil {
         l.ll.Remove(e) // 从链表中移除这个元素
         node := e.Value.(*CacheNode) // 让这个value等于这个cacheNode
         delete(l.cache, node.key) // 从map中删除
         if l.Call != nil {
            l.Call(node.key, node.value)
         }
      }
   }
   return nil
}
  • 获取一个key
func (l *LRUCache) Get(key interface{}) (val interface{}, ok bool) {
   if l.cache == nil {
      return
   }
   if ele, ok := l.cache[key]; ok {
      l.ll.PushFront(ele) // 使用过,就将这个移到最前面
      return ele.Value.(*CacheNode).value, ok
   }
   return
}
  • 删除元素的函数
func (l *LRUCache) Delete(key interface{}) {
   if ele, ok := l.cache[key]; ok {
      l.ll.Remove(ele)     // 删除就将这个元素从链表中移除
      delete(l.cache, ele) // 从map中删除
      if l.Call != nil {
         node := ele.Value.(*CacheNode)
         l.Call(node.key, node.value)
      }
   }
}