Skip to content

Commit 87866f2

Browse files
author
百里
committed
新增双链表, FIFO, LFU, LRU算法
1 parent 2255d21 commit 87866f2

20 files changed

+1093
-13
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.vscode
2+
.idea
23
.DS_Store
34
Desktop.ini

.idea/markdown-navigator.xml

Lines changed: 82 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/watcherTasks.xml

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cache/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# FIFO,LRU和LFU都是内存管理的页面置换算法。
2+
3+
## FIFO 先进先出算法
4+
> 借用双链表实现
5+
6+
1. [代码实现](fifo.go)
7+
8+
## LRU 最少最近淘汰算法.
9+
> 借用双链表实现,将最近使用的数据添加到头部.容量满时,淘汰尾部数据.
10+
11+
1. [代码实现](lru.go)
12+
13+
## LFU 最不常用淘汰算法.
14+
> 借用双链表实现, 将每一个节点数据添加一个使用频率值, 相同使用频率放在一个链表里. 当容量满时,则淘汰频率低的链表.
15+
16+
1. [代码实现](lfu.go)

Cache/fifo.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package Cache
2+
3+
import (
4+
"github.com/yezihack/math/DoubleLinedList"
5+
)
6+
7+
/* FIFO(first in first out) 先进先出淘汰算法*/
8+
9+
/*
10+
解题思路:
11+
1. 借用双链表实现FIFO
12+
2. 借用map实现缓存, 避免对链表的搜索
13+
*/
14+
15+
//定义FIFO的结构体
16+
type FIFOCache struct {
17+
double *DoubleLinedList.DoubleList
18+
cache map[int]*DoubleLinedList.DoubleNode
19+
}
20+
21+
//实例对象
22+
func NewFIFO(capacity uint) *FIFOCache {
23+
fifo := FIFOCache{}
24+
fifo.double = DoubleLinedList.New(capacity)
25+
fifo.cache = make(map[int]*DoubleLinedList.DoubleNode)
26+
return &fifo
27+
}
28+
29+
//获取值
30+
func (f *FIFOCache) Get(key int) *DoubleLinedList.DoubleNode {
31+
//判断是否在缓存中
32+
if node, ok := f.cache[key]; ok { //存在的话
33+
return node
34+
} else { //不存在的话
35+
return nil
36+
}
37+
}
38+
39+
//添加元素
40+
func (f *FIFOCache) Put(key int, data interface{}) bool {
41+
//判断是否存在缓存中
42+
if node, ok := f.cache[key]; ok { //存在的话
43+
//更新数据,删除链表, 再添加到链表中
44+
node.Value = data
45+
f.double.Remove(node)
46+
f.double.Append(node)
47+
} else { //不存在的话
48+
////判断容量是否满了
49+
//if f.double.Size >= f.double.Capacity { //满了.
50+
// //删除头部数据,因为我们是追加, 头部数据是最早添加的
51+
// f.double.RemoveHead()
52+
// node = DoubleLinedList.Node(key, data)
53+
// f.double.Append(node)
54+
// f.cache[key] = node
55+
//} else { //没满
56+
// node = DoubleLinedList.Node(key, data)
57+
// f.double.Append(node)
58+
// f.cache[key] = node
59+
//}
60+
/**************将以上逻辑简化*****************/
61+
if f.double.Size >= f.double.Capacity { //满了.
62+
//删除头部数据,因为我们是追加, 头部数据是最早添加的
63+
f.double.RemoveHead()
64+
}
65+
node = DoubleLinedList.Node(key, data)
66+
f.double.Append(node)
67+
f.cache[key] = node
68+
}
69+
return true
70+
}
71+
72+
//获取链表大小
73+
func (f *FIFOCache) GetSize() uint {
74+
return f.double.Size
75+
}
76+
77+
//打印
78+
func (f *FIFOCache) Print() {
79+
f.double.Print()
80+
}

Cache/fifo_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package Cache
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestFIFO_Put(t *testing.T) {
9+
fifo := NewFIFO(3)
10+
fifo.Put(1, 1)
11+
fifo.Print()
12+
fifo.Put(2, 2)
13+
fifo.Print()
14+
fifo.Put(3, 3)
15+
fifo.Print()
16+
fifo.Put(4, 4)
17+
fifo.Print()
18+
fifo.Put(5, 5)
19+
fifo.Print()
20+
fifo.Put(3, "我的一个3")
21+
fifo.Print()
22+
}
23+
func TestFIFO_GetSize(t *testing.T) {
24+
f := NewFIFO(2)
25+
f.Put(0, 0)
26+
if f.GetSize() != 1 {
27+
t.Errorf("size:%d, errSize: %d\n", 1, f.GetSize())
28+
}
29+
f.Put(1, 1)
30+
if f.GetSize() != 2 {
31+
t.Errorf("size:%d, errSize: %d\n", 2, f.GetSize())
32+
}
33+
f.Put(3, 3)
34+
f.Print()
35+
if f.GetSize() != 2 {
36+
t.Errorf("size:%d, errSize: %d\n", 2, f.GetSize())
37+
}
38+
}
39+
func TestFIFOCache_Get(t *testing.T) {
40+
f := NewFIFO(10)
41+
f.Put(1, "abc")
42+
node := f.Get(1)
43+
if node.Key != 1 {
44+
t.Errorf("want: %d, err: %v", 1, node.Key)
45+
}
46+
if f.GetSize() != 1 {
47+
t.Errorf("want: %d, err: %v", 1, f.GetSize())
48+
}
49+
for i := 0; i < 100; i++ {
50+
f.Put(i, fmt.Sprintf("i:%d", i))
51+
}
52+
if f.GetSize() != 10 {
53+
t.Errorf("want: %d, err:%v", 10, f.GetSize())
54+
}
55+
fmt.Println(f.Get(99))
56+
fmt.Println(f.Get(1001))
57+
}

0 commit comments

Comments
 (0)