使用双向链表实现LRU算法
//使用双向链表实现的LRU算法
type LRUCache struct {
Capacity int
Store map[int]*DbNode
List *DbList
}
//链表节点
type DbNode struct {
Key int
Data int
Pre *DbNode
Next *DbNode
}
//双向链表
type DbList struct {
Size int
mutex *sync.RWMutex
Head *DbNode
Tail *DbNode
}
//往链表头部插入数据
func (d *DbList) AppendFront(node *DbNode) bool {
if node == nil {
return false
}
d.mutex.RLock()
defer d.mutex.RUnlock()
if d.Size == 0 {
d.Head, d.Tail = node, node
d.Size++
} else {
node.Next = d.Head
d.Head.Pre = node
d.Head = node
d.Size++
}
return true
}
//将指定的链表节点移动到头部
func (d *DbList) MoveFront(node *DbNode) bool {
if node == nil {
return false
}
if d.Size <= 1 {
return true
}
d.mutex.Lock()
defer d.mutex.Unlock()
switch node {
case d.Head:
return true
case d.Tail:
node.Pre.Next = nil
d.Tail = node.Pre
node.Pre, node.Next, d.Head.Pre = nil, d.Head, node
d.Head = node
return true
default:
node.Pre.Next, node.Next.Pre = node.Next, node.Pre
d.Head.Pre, node.Next, node.Pre = node, d.Head, nil
d.Head = node
return true
}
}
//删除指定的节点
func (d *DbList) Remove(node *DbNode) bool {
if node == nil {
return false
}
if d.Size == 0 {
return true
}
d.mutex.Lock()
defer d.mutex.Unlock()
defer func(d *DbList, node *DbNode) {
if err := recover(); err != nil {
fmt.Println(err)
}
}(d, node)
if node == d.Head && node == d.Tail {
d.Head, d.Tail = nil, nil
} else if node == d.Head {
node.Next.Pre = nil
d.Head = node.Next
} else if node == d.Tail {
node.Pre.Next = nil
d.Tail = node.Pre
} else {
node.Pre.Next, node.Next.Pre = node.Next, node.Pre
}
d.Size--
return true
}
//初始化LRU缓存
func Constructor(capacity int) LRUCache {
return LRUCache{
Capacity: capacity,
Store: make(map[int]*DbNode),
List: &DbList{
Size: 0,
mutex: new(sync.RWMutex),
},
}
}
//获取LRU缓存数据
func (this *LRUCache) Get(key int) int {
if node, ok := this.Store[key]; ok {
if ok := this.List.MoveFront(node); ok {
return node.Data
}
}
return -1
}
//插入或者更新缓存
func (this *LRUCache) Put(key int, value int) {
//判断是否有数据
if node, ok := this.Store[key]; ok {
this.List.MoveFront(node)
node.Data = value
return
}
//判断是否超过了容量,超过则清除最久
if this.List.Size >= this.Capacity {
delete(this.Store, this.List.Tail.Key)
this.List.Remove(this.List.Tail)
}
//新增数据
node := &DbNode{
Key: key,
Data: value,
}
this.Store[key] = node
this.List.AppendFront(node)
}
//
//["LRUCache","put","get","put","get","get"]
//[[1],[2,1],[2],[3,2],[2],[3]]
func main() {
var str = "[[1],[2,1],[2],[3,2],[2],[3]]"
var value [][]int
var once sync.Once
var cache LRUCache
if err := json.Unmarshal([]byte(str), &value); err != nil {
log.Printf("[ERROR] 反序列化失败, 错误信息:%s \n", err.Error())
return
}
for index, item := range value {
once.Do(func() {
cache = Constructor(item[0])
})
switch len(item) {
case 1:
fmt.Println(cache.Get(item[0]))
case 2:
cache.Put(item[0], item[1])
}
}
}