Skip to content

Commit fbd81c3

Browse files
committed
LRU算法
1 parent a067df5 commit fbd81c3

File tree

4 files changed

+326
-29
lines changed

4 files changed

+326
-29
lines changed

02.链表/01.单链表.go

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,134 @@
33
* @Date: 2020-02-10 22:49:50
44
* @LastEditTime : 2020-02-11 16:17:52
55
* @LastEditors : 百里
6-
* @Description:
6+
* @Description: 单链表操作.
77
* @FilePath: \leetcode\02.链表\01.单链表.go
88
* @https://github.com/yezihack
99
*/
1010
package linked
1111

12+
import "fmt"
13+
1214
type SNode struct {
13-
data int
14-
next *SNode //后继节点
15+
data int //数据存储
16+
next *SNode //后继指针
1517
}
1618

1719
type ISingleLinked interface {
18-
AddHead(data int) //插入头节点
19-
Append(data int) //追加节点,即添加到尾部.
20+
AddHead(data int) *SNode //插入头节点
21+
Append(data int) *SNode //追加节点,即添加到尾部.
2022
RemoveHead() bool //删除头节点
2123
RemoveTail() bool //删除尾节点
2224
RemoveNode(node *SNode) bool //删除节点
2325
Print() string //打印链表
2426
}
27+
28+
//声明单链表结构体.
29+
type SLinked struct {
30+
count int //length node
31+
head *SNode //head node
32+
tail *SNode //tail node
33+
}
34+
35+
//实例一下
36+
func NewSLinked() *SLinked {
37+
return &SLinked{}
38+
}
39+
40+
//添加头节点
41+
func (s *SLinked) AddHead(data int) *SNode {
42+
node := &SNode{data: data} //创建一个新节点.
43+
if s.head == nil { //如果头指针为空的话.
44+
s.head = node //node指向头指针
45+
s.tail = node //node也指向尾指针. 即头尾指针指向同一个节点.
46+
} else {
47+
//实现头插法.
48+
node.next = s.head //新的节点node后继指针指向头节点head
49+
s.head = node //将node设置为新的头指针head.
50+
}
51+
s.count++
52+
return node
53+
}
54+
55+
//追加操作.
56+
func (s *SLinked) Append(data int) *SNode {
57+
node := &SNode{data: data} //创建一个新节点.
58+
if s.tail == nil { //如果尾指针为空的话.
59+
s.head = node //node指向头指针
60+
s.tail = node //node也指向尾指针. 即头尾指向同一个节点.
61+
} else {
62+
//实现尾插法
63+
s.tail.next = node //尾指针tail的后继指针指向新节点node
64+
s.tail = node //将新节点node设置为新的尾指针tail
65+
}
66+
s.count++
67+
return node
68+
}
69+
70+
//移除头节点.
71+
func (s *SLinked) RemoveHead() bool {
72+
if s.count == 0 { //如果无节点则返回False
73+
return false
74+
}
75+
s.head = s.head.next //将头指针的后继指针设置为新的头指针
76+
s.count--
77+
return true
78+
}
79+
80+
func (s *SLinked) RemoveTail() bool {
81+
if s.count == 0 { //链表长度为0的话.则返回False
82+
return false
83+
} else if s.count == 1 { //链表长度为1的话,设置为空
84+
s.tail = nil
85+
s.head = nil
86+
} else {
87+
tailPre := s.head //定义一个指针
88+
for i := 0; i < s.count-2; i++ { //循环count-2
89+
tailPre = tailPre.next
90+
}
91+
tailPre.next = nil
92+
s.tail = tailPre
93+
}
94+
s.count--
95+
return true
96+
}
97+
98+
func (s *SLinked) RemoveNode(node *SNode) bool {
99+
if node == s.head {
100+
s.head = s.head.next
101+
} else if node == s.tail {
102+
tailPre := s.head
103+
for i := 0; i < s.count-2; i++ {
104+
tailPre = tailPre.next
105+
}
106+
tailPre.next = nil
107+
s.tail = tailPre
108+
} else {
109+
l := s.head
110+
var pre *SNode
111+
for i := 0; i < s.count-1; i++ {
112+
if l == node {
113+
break
114+
}
115+
pre = l
116+
l = l.next
117+
}
118+
if pre.next != nil {
119+
pre.next = pre.next.next
120+
}
121+
}
122+
return true
123+
}
124+
125+
func (s *SLinked) Print() string {
126+
str := ""
127+
head := s.head
128+
for head != nil {
129+
str += fmt.Sprint(head.data)
130+
head = head.next
131+
if head != nil {
132+
str += "=>"
133+
}
134+
}
135+
return str
136+
}

02.链表/01.单链表_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package linked
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestSLinked_AddHead(t *testing.T) {
9+
link := NewSLinked()
10+
link.AddHead(1)
11+
link.AddHead(2)
12+
link.AddHead(3)
13+
var want string
14+
want = "3=>2=>1"
15+
if link.Print() != want {
16+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
17+
}
18+
}
19+
20+
func TestSLinked_Append(t *testing.T) {
21+
link := NewSLinked()
22+
link.Append(1)
23+
link.Append(2)
24+
link.Append(3)
25+
var want string
26+
want = "1=>2=>3"
27+
if link.Print() != want {
28+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
29+
}
30+
}
31+
32+
func TestSLinked_RemoveHead(t *testing.T) {
33+
link := NewSLinked()
34+
link.Append(1)
35+
link.Append(2)
36+
link.Append(3)
37+
link.RemoveHead()
38+
var want string
39+
want = "2=>3"
40+
if link.Print() != want {
41+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
42+
}
43+
link.RemoveHead()
44+
want = "3"
45+
if link.Print() != want {
46+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
47+
}
48+
link.RemoveHead()
49+
want = ""
50+
if link.Print() != want {
51+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
52+
}
53+
}
54+
55+
func TestSLinked_RemoveTail(t *testing.T) {
56+
link := NewSLinked()
57+
link.Append(1)
58+
link.Append(2)
59+
link.Append(3)
60+
link.RemoveTail()
61+
var want string
62+
want = "1=>2"
63+
if link.Print() != want {
64+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
65+
}
66+
link.RemoveTail()
67+
want = "1"
68+
if link.Print() != want {
69+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
70+
}
71+
link.RemoveTail()
72+
want = ""
73+
if link.Print() != want {
74+
t.Errorf("Append()=%s, want:%s", link.Print(), want)
75+
}
76+
}
77+
func TestSLinked_RemoveNode(t *testing.T) {
78+
link := NewSLinked()
79+
s1 := link.Append(1)
80+
s2 := link.Append(2)
81+
s3 := link.Append(3)
82+
_ = s1 //2=>3
83+
_ = s2 //1=>3
84+
_ = s3 //1=>2
85+
link.RemoveNode(s3)
86+
//link.RemoveNode(s1)
87+
//link.RemoveNode(s2)
88+
fmt.Println(link.Print())
89+
}

02.链表/04.LRU.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package linked
2+
3+
//定义节点
4+
type Node struct {
5+
key, value int //key:value
6+
prev, next *Node //前驱指针与后继指针
7+
}
8+
9+
//定义LRU结构体
10+
type LRUCache struct {
11+
capacity int //上限容量
12+
MapCache map[int]*Node //map缓存节点,实现O(1)操作
13+
head, end *Node //头节点与尾结点
14+
}
15+
16+
func NewLRUCache(capacity int) *LRUCache {
17+
return &LRUCache{
18+
capacity: capacity,
19+
MapCache: make(map[int]*Node), //初使化,map必须初使化才能用.
20+
head: nil,
21+
end: nil,
22+
}
23+
}
24+
25+
//获取操作
26+
//1. 判断key是否存在
27+
//---存在:从缓存里获取节点信息,然后删除,再添加到链表的头部位置.
28+
//---不存在:直接返回-1
29+
func (this *LRUCache) Get(key int) int {
30+
node, ok := this.MapCache[key] //从缓冲中取出
31+
if !ok { //缓存不存在则返回-1
32+
return -1
33+
}
34+
this.remove(node) //删除节点
35+
this.setHeader(node) //添加到头节点
36+
return node.value //返回数据.
37+
}
38+
func (this *LRUCache) Put(key, value int) {
39+
if node, ok := this.MapCache[key]; ok {
40+
node.value = value
41+
this.remove(node)
42+
this.setHeader(node)
43+
} else {
44+
if len(this.MapCache) >= this.capacity {
45+
delete(this.MapCache, key) //删除缓存中的数据.
46+
this.remove(this.end) //再移除最后一个节点
47+
}
48+
node := &Node{key: key, value: value}
49+
this.MapCache[key] = node
50+
this.setHeader(node)
51+
}
52+
}
53+
54+
//移除节点
55+
//1.判断前驱是否为空
56+
//是:此节点就是头节点.
57+
//否:不是头节点,则node.pre.next = node.next
58+
//2.判断后继是否为空
59+
//是:此节点就是尾节点.
60+
//否:不是尾节点,则node.next.pre = node.pre
61+
func (this *LRUCache) remove(node *Node) {
62+
if node.prev == nil {
63+
this.head = node.next
64+
} else {
65+
node.prev.next = node.next
66+
}
67+
if node.next == nil {
68+
this.end = node.prev
69+
this.end.next = nil
70+
} else {
71+
node.next.prev = node.prev
72+
}
73+
}
74+
75+
//设置头节点.
76+
//头节点的特性: 前驱指针为空.
77+
//1.判断头节点head是否为空
78+
//是: 直接设置
79+
//否: 将当前的节点设置为第二个节点, node设置为新的头节点.
80+
//2.判断end尾节点是否为空
81+
//是:直接设置
82+
//否:不操作
83+
func (this *LRUCache) setHeader(node *Node) {
84+
node.prev = nil
85+
if this.head == nil {
86+
this.head = node
87+
} else {
88+
head := this.head
89+
node.next = head
90+
head.prev = node
91+
this.head = node
92+
}
93+
if this.end == nil {
94+
this.end = node
95+
}
96+
}

0 commit comments

Comments
 (0)