小贴士
在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节点和删除节点的时候就不需要检查相邻的节点是否存在。
步骤
- 建立LRUCahe结构体作为实现LRU缓存的对象
- 结构体中包含当前大小和容量
- 包含map结构和链表结构
- map与链表关联
- 将功能细分如:初始化LRUCache结构体
- 初始化结点,在put时候使用
- get,put操作也可以将对链表的操作单独拿出来,如:
- 在头节点加节点addToHand (put使用)
- 删除节点removeNode (put超出容量时使用)
- 移动节点(也就是删除节点+加节点)(重复get使用)
- 删除尾节点 (put超出容量时使用)
type LRUCache struct {
size int
capacity int
cache map[int]*LinkedNode
head,tail *LinkedNode
}
type LinkedNode struct {
pre,next *LinkedNode
key,value int
}
func InitLinkedNode(key,value int) *LinkedNode{
return &LinkedNode{
key : key,
value : value,
}
}
func Constructor(capacity int) LRUCache {
l := LRUCache{
capacity : capacity,
cache : map[int]*LinkedNode{},
head : InitLinkedNode(0,0),
tail : InitLinkedNode(0,0),
}
l.head.next = l.tail
l.tail.pre = l.head
return l
}
func (this *LRUCache) Get(key int) int {
if node,ok := this.cache[key]; ok {
this.moveToHand(node)
return node.value
}
return -1
}
func (this *LRUCache) Put(key int, value int) {
node,ok := this.cache[key]
if !ok {
node = InitLinkedNode(key,value)
this.cache[key] = node
this.addToHand(node)
this.size++
if this.size > this.capacity {
removed := this.removeTail()
delete(this.cache,removed.key)
this.size--
}
return
}
node.value = value
this.moveToHand(node)
}
func (this *LRUCache) addToHand(node *LinkedNode) {
node.next = this.head.next
node.pre = this.head
this.head.next = node
node.next.pre = node
}
func (this *LRUCache) removeNode(node *LinkedNode) {
node.pre.next = node.next
node.next.pre = node.pre
}
func (this *LRUCache) moveToHand(node *LinkedNode) {
this.removeNode(node)
this.addToHand(node)
}
func (this *LRUCache) removeTail() *LinkedNode {
node := this.tail.pre
this.removeNode(node)
return node
}
/**
* Your LRUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/