-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathlfu.go
128 lines (117 loc) · 2.97 KB
/
lfu.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package Cache
import (
"fmt"
"github.com/yezihack/math/DoubleLinedList"
"math"
)
/* LFU(least frequently used) 最不常用使用淘汰算法 */
/*
解题思路:
1. 需要记录使用次数,相同的使用次数记录在一起
2. 添加, 获取都记录为一次.
3. 当容量满时,淘汰次数最少的链表
*/
//定义一个切片链表
type FreqList struct {
list []*DoubleLinedList.DoubleNode
}
//定义一个最不常用的结构体
type LFUCache struct {
cache map[int]*DoubleLinedList.DoubleNode //缓存节点
cacheFreq map[int]*DoubleLinedList.DoubleList //key:为频率, value:为频率链表
capacity int //容量大小
size int //当前大小
}
func NewLFUCache(capacity int) *LFUCache {
f := LFUCache{}
f.capacity = capacity
f.cache = make(map[int]*DoubleLinedList.DoubleNode)
f.cacheFreq = make(map[int]*DoubleLinedList.DoubleList, 0)
return &f
}
//更新频率
func (f *LFUCache) updateFreq(node *DoubleLinedList.DoubleNode) {
// 删除频率MAP里的节点,再加+1, 再存入
freq := node.Freq
//删除频率里的MAP节点
node = f.cacheFreq[freq].Remove(node)
if f.cacheFreq[freq].Size == 0 { //如果这个频率里的链表大小为0则删除掉
delete(f.cacheFreq, freq)
}
//更新, .
freq++
node.Freq = freq
//新的频率了, 需要判断是否在缓存中
if _, ok := f.cacheFreq[freq]; !ok { //不存在缓存中, 则创建新的.
f.cacheFreq[freq] = DoubleLinedList.New(math.MaxInt32)
}
f.cacheFreq[freq].Append(node)
}
//获取
func (f *LFUCache) Get(key int) *DoubleLinedList.DoubleNode {
if node, ok := f.cache[key]; ok {
f.updateFreq(node)
return node
}
return nil
}
//使用
func (f *LFUCache) Put(key int, data interface{}) bool {
if f.capacity == 0 {
return false
}
//判断是否在缓存中
if node, ok := f.cache[key]; ok { //缓存里有
node.Value = data
f.updateFreq(node)
return true
} else { //缓存里无
if f.size == f.capacity { //满了
//淘汰掉频率最低的数据.
freqKey := f.MinFreq()
node = f.cacheFreq[freqKey].Head
delete(f.cache, node.Key)
delete(f.cacheFreq, freqKey)
f.size--
}
//添加数据.
node = DoubleLinedList.Node(key, data)
node.Freq = 1
if _, ok := f.cacheFreq[node.Freq]; !ok {
f.cacheFreq[node.Freq] = DoubleLinedList.New(math.MaxUint)
}
f.cacheFreq[node.Freq].Append(node)
f.cache[key] = node
f.size++
}
return true
}
//求出MAP里最小值的下标
func (f *LFUCache) MinFreq() int {
min := math.MaxInt
for freqKey := range f.cacheFreq {
if freqKey < min {
min = freqKey
}
}
return min
}
//获取最大频率下标
func (f *LFUCache) MaxFreq() int {
max := 0
for freqKey := range f.cacheFreq {
if freqKey > max {
max = freqKey
}
}
return max
}
//打印
func (f *LFUCache) Print() {
fmt.Println("---------------------------")
for k := range f.cacheFreq {
fmt.Printf("freq:%d \n", k)
f.cacheFreq[k].Print()
}
fmt.Println("---------------------------")
}