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)
}
}
}