设计一个lru机制,首先是思路:
首先用一个双向链表来存储一个节点
type DLinkNode struct{
key, value int
pre, next *DLinkNode
}
整个LRU包括当前长度、容量、头节点、尾节点、hash存储
type LRUCache struct {
size int
capacity int
cache map[int]*DLinkNode
head, tail *DLinkNode
}
数据结构定义好以后,就是操作了,主要包括,初始化一个节点,获取一个节点的值,存储一个极点的值
读操作,首先判断hash中是否有该元素,没有的话,直接返回-1;否则返回该节点值,并将该元素移动至队首,见代码:
func (this *LRUCache) Get(key int) int {
if _, ok := this.cache[key];!ok{
return -1
}
//移动位置
node := this.cache[key]
this.moveToHead(node)
//返回结果
return node.value
}
写操作,首先判断hash中是否有该元素,有的话,直接将该元素移动至队首;
否则初始化节点,将该元素插入队首,插入成功后,判断链表长度是否超过容量,不超过,直接返回;超过,删除队尾元素,这里要注意一点,也要删除hash中对应的key值。
完整代码,见图
type LRUCache struct {
size int
capacity int
cache map[int]*DLinkNode
head, tail *DLinkNode
}
type DLinkNode struct{
key, value int
pre, next *DLinkNode
}
func initDLinkNode(key, value int)*DLinkNode{
return &DLinkNode{
key:key,
value:value,
}
}
func Constructor(capacity int) LRUCache {
l := LRUCache{
capacity: capacity,
cache: map[int]*DLinkNode{},
head: initDLinkNode(0, 0),
tail: initDLinkNode(0, 0),
}
l.head.next = l.tail
l.tail.pre = l.head
return l
}
func (this *LRUCache) Get(key int) int {
if _, ok := this.cache[key];!ok{
return -1
}
//移动位置
node := this.cache[key]
this.moveToHead(node)
//返回结果
return node.value
}
func (this *LRUCache)moveToHead(node *DLinkNode){
this.removeNode(node)
this.addToHead(node)
}
func (this *LRUCache)removeNode(node *DLinkNode){
node.pre.next = node.next
node.next.pre = node.pre
}
func (this *LRUCache)addToHead(node *DLinkNode){
node.next = this.head.next
node.pre = this.head
this.head.next.pre = node
this.head.next = node
}
func (this *LRUCache) Put(key int, value int) {
if _, ok := this.cache[key];ok{
node := this.cache[key]
node.key = value
this.moveToHead(node)
}else{
node := initDLinkNode(key, value)
this.cache[key] = node
this.addToHead(node)
this.size++
if this.size > this.capacity{
removed := this.removeTail()
delete(this.cache, removed.key)
this.size--
}
}
}
func (this *LRUCache)removeTail() *DLinkNode{
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);
*/