golang实现LRU算法
golang实现LRU算法
Least Recently used
本文仅列出完成 LeetCode146.LRU缓存的思路
实现:
- 哈希表:键为关键字key,值为*DLinkNode,映射对应链表中的节点
- 双向链表:靠近头部的元素是最近使用的,靠近尾部则是最久未使用的
实现LRU并不难,建议先把算法的各个函数的框架先列好,再去敲代码!!
结构:
//LRUCache定义
type LRUCache struct {
size int
capacity int
cache map[int]*DLinkNode
head, tail *DLinkNode
}
//双向链表节点
type DLinkNode struct {
key,value int
pre, next *DLinkNode
}
功能:
//缓存实现的功能
//如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
func (this *LRUCache) Get(key int)
//如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出最久未使用的关键字
func (this *LRUCache) Put(key int, value int)
//一些链表的操作
//初始化一个新节点
func initDLinkedNode(key, value int) *DLinkNode
//更新到链头,用于key命中的情况下,不改变缓存的size
func (this *LRUCache) UpdateToHead(node *DLinkNode)
//删除链尾元素
func (this *LRUCache) DeleteLast()
//添加新元素,用于key未命中时,size+1
func (this *LRUCache) InsertNewHead(node *DLinkNode)
以下附上完整代码
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,value,nil,nil}
}
func Constructor(capacity int) LRUCache {
l := LRUCache{
0,
capacity,
map[int]*DLinkNode{},
InitDlinkNode(0, 0),
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.UpdateToHead(node)
return node.value
}
func (this *LRUCache) Put(key int, value int) {
if _,ok := this.cache[key];!ok {
node := InitDlinkNode(key, value)
for this.size >= this.capacity {
this.DeleteLast()
}
this.cache[key] = node
this.InsertNewHead(node)
}else {
node := this.cache[key]
node.value = value
this.UpdateToHead(node)
}
}
func (this *LRUCache) UpdateToHead(node *DLinkNode) {
node.Pre.Next = node.Next
node.Next.Pre = node.Pre
temp := this.Head.Next
this.Head.Next = node
node.Pre = this.Head
node.Next = temp
temp.Pre = node
}
func (this *LRUCache) DeleteLast() {
node := this.Tail.Pre
this.Tail.Pre = node.Pre
node.Pre.Next = node.Next
node.Pre = nil
node.Next = nil
this.size--
delete(this.cache, node.key)
}
func (this *LRUCache) InsertNewHead(node *DLinkNode) {
temp := this.Head.Next
this.Head.Next = node
node.Pre = this.Head
temp.Pre = node
node.Next = temp
this.size++
}