面云账户时候问了LRU,具体实现的方式是map+双链表。Set和Get的时间复杂度都是O(1)。完整写一遍复习一下, 仅作记录
/**
* @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.head.prev = node
} else {
l.tail = node
}
node.prev = nil
node.next = l.head
l.head = node
}