1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00
Files
lancet/algorithm/lru_cache.go
2022-03-11 17:05:55 +08:00

100 lines
1.8 KiB
Go

package algorithm
type lruNode[K comparable, V any] struct {
key K
value V
pre *lruNode[K, V]
next *lruNode[K, V]
}
// newLruNode return a lruNode pointer
func newLruNode[K comparable, V any](key K, value V) *lruNode[K, V] {
return &lruNode[K, V]{
key: key,
value: value,
pre: nil,
next: nil,
}
}
// LRUCache lru cache
type LRUCache[K comparable, V any] struct {
cache map[K]*lruNode[K, V]
head *lruNode[K, V]
tail *lruNode[K, V]
capacity int
length int
}
// NewLRUCache return a LRUCache pointer
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
return &LRUCache[K, V]{
cache: make(map[K]*lruNode[K, V]),
head: nil,
tail: nil,
capacity: capacity,
length: 0,
}
}
// Get value of key from lru cache
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
var value V
node, ok := l.cache[key]
if node == nil || !ok {
return value, false
}
l.moveToHead(node)
return node.value, true
}
// Put value of key into lru cache
func (l *LRUCache[K, V]) Put(key K, value V) {
node, ok := l.cache[key]
if node == nil || !ok {
newNode := newLruNode(key, value)
l.cache[key] = newNode
l.addNode(newNode)
l.length++
if l.length > l.capacity {
tail := l.popTail()
delete(l.cache, tail.key)
l.length--
}
}
node.value = value
l.moveToHead(node)
}
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
node.pre = l.head
node.next = l.head.next
l.head.next.pre = node
l.head.next = node
}
func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) {
pre := node.pre
next := node.next
pre.next = next
next.pre = pre
}
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
l.deleteNode(node)
l.addNode(node)
}
func (l *LRUCache[K, V]) popTail() *lruNode[K, V] {
node := l.tail.pre
l.deleteNode(node)
return node
}