Skip to content

Commit 7921f2d

Browse files
committed
add LRU
1 parent f2917b7 commit 7921f2d

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

Algorithm/Others/LRU/lru.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/**
2+
* Author: Juntaran
3+
* Email: Jacinthmail@gmail.com
4+
* Date: 2018/12/9 20:47
5+
*/
6+
7+
package LRU
8+
9+
import (
10+
"container/list"
11+
"github.com/pkg/errors"
12+
)
13+
14+
// CacheNode 结构
15+
type CacheNode struct {
16+
Key interface{}
17+
Value interface{}
18+
}
19+
20+
// 初始化缓存节点
21+
func NewCacheNode(k, v interface{}) *CacheNode {
22+
return &CacheNode{k, v}
23+
}
24+
25+
// LRU 结构 双链表+map
26+
type LRUCache struct {
27+
Capacity int
28+
lruList *list.List
29+
cacheMap map[interface{}]*list.Element // list.Element 就是 listnode
30+
}
31+
32+
// 初始化 LRU 结构
33+
func NewLRUCache(capacity int) *LRUCache {
34+
return &LRUCache{
35+
capacity,
36+
list.New(),
37+
make(map[interface{}]*list.Element),
38+
}
39+
}
40+
41+
// 返回当前 lru 长度
42+
func (lru *LRUCache) Size() int {
43+
return lru.lruList.Len()
44+
}
45+
46+
// lru 插入值
47+
func (lru *LRUCache) Set(k, v interface{}) error {
48+
if lru.lruList == nil {
49+
return errors.New("LRUCache NOT INIT")
50+
}
51+
52+
if e, ok := lru.cacheMap[k]; ok {
53+
// 插入的 key 已经存在,把它挪到顶端
54+
// 之后更新对应的 value
55+
lru.lruList.MoveToFront(e)
56+
e.Value.(*CacheNode).Value = v
57+
return nil
58+
}
59+
60+
// 如果不存在,插入新元素到链表顶端
61+
newElement := lru.lruList.PushFront(&CacheNode{k, v})
62+
lru.cacheMap[k] = newElement
63+
64+
// 判断是否链表已超过 capacity
65+
// 如果未超过,return
66+
// 否则删除末端
67+
if lru.lruList.Len() > lru.Capacity{
68+
// 双链表移除最后一个
69+
lastElement := lru.lruList.Back()
70+
if lastElement == nil {
71+
return nil
72+
}
73+
lru.lruList.Remove(lastElement)
74+
75+
// 从 map 中删除
76+
delete(lru.cacheMap, lastElement.Value.(*CacheNode).Key)
77+
}
78+
return nil
79+
}
80+
81+
// lru 查询值
82+
func (lru *LRUCache) Get(k interface{}) (v interface{}, ret bool, err error) {
83+
if lru.cacheMap == nil {
84+
return v, false, errors.New("LRUCache NOT INIT")
85+
}
86+
87+
// 如果 map 中存在该 key
88+
// 双链表把它移到顶端
89+
if e, ok := lru.cacheMap[k]; ok {
90+
lru.lruList.MoveToFront(e)
91+
return e.Value.(*CacheNode).Value, true, nil
92+
}
93+
94+
// map 中未查找到,返回 false
95+
return v, false, nil
96+
}
97+
98+
// lru 删除
99+
func (lru *LRUCache) Remove(k interface{}) bool {
100+
if lru.cacheMap == nil {
101+
return false
102+
}
103+
104+
// map 中存在该 key
105+
// 分别从双链表和 map 中删除
106+
if e, ok := lru.cacheMap[k]; ok {
107+
waitToDelete := e.Value.(*CacheNode)
108+
delete(lru.cacheMap, waitToDelete.Key)
109+
lru.lruList.Remove(e)
110+
return true
111+
}
112+
return false
113+
}

Algorithm/Others/LRU/main/main.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Author: Juntaran
3+
* Email: Jacinthmail@gmail.com
4+
* Date: 2018/12/9 21:23
5+
*/
6+
7+
package main
8+
9+
import (
10+
"fmt"
11+
12+
"github.com/Juntaran/Golang_Algorithm/Algorithm/Others/LRU"
13+
)
14+
15+
func main() {
16+
lru := LRU.NewLRUCache(3)
17+
18+
lru.Set(10,"value1")
19+
lru.Set(20,"value2")
20+
lru.Set(30,"value3")
21+
lru.Set(10,"value4")
22+
lru.Set(50,"value5")
23+
24+
fmt.Println("LRU Size:",lru.Size())
25+
v, get, _ := lru.Get(30)
26+
if get {
27+
fmt.Println("Get(30) : ",v)
28+
}
29+
30+
if lru.Remove(30) {
31+
fmt.Println("Remove(30) : true ")
32+
} else {
33+
fmt.Println("Remove(30) : false ")
34+
}
35+
fmt.Println("LRU Size:", lru.Size())
36+
}

0 commit comments

Comments
 (0)