github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/lru_cache/lru_cache.go (about) 1 package lru_cache 2 3 const ( 4 hostbit = uint64(^uint(0)) == ^uint64(0) 5 LENGTH = 128 6 ) 7 8 type lruNode struct { 9 prev *lruNode 10 next *lruNode 11 12 key int // lru key 13 value int // lru value 14 15 hnext *lruNode // 拉链 16 } 17 18 type LRUCache struct { 19 node []lruNode // hash list 20 21 head *lruNode // lru head node 22 tail *lruNode // lru tail node 23 24 capacity int // 25 used int // 26 } 27 28 func Constructor(capacity int) LRUCache { 29 return LRUCache{ 30 node: make([]lruNode, LENGTH), 31 head: nil, 32 tail: nil, 33 capacity: capacity, 34 used: 0, 35 } 36 } 37 38 func (this *LRUCache) Get(key int) int { 39 if this.tail == nil { 40 return -1 41 } 42 43 if tmp := this.searchNode(key); tmp != nil { 44 this.moveToTail(tmp) 45 return tmp.value 46 } 47 return -1 48 } 49 50 func (this *LRUCache) Put(key int, value int) { 51 // 1. 首次插入数据 52 // 2. 插入数据不在 LRU 中 53 // 3. 插入数据在 LRU 中 54 // 4. 插入数据不在 LRU 中, 并且 LRU 已满 55 56 if tmp := this.searchNode(key); tmp != nil { 57 tmp.value = value 58 this.moveToTail(tmp) 59 return 60 } 61 this.addNode(key, value) 62 63 if this.used > this.capacity { 64 this.delNode() 65 } 66 } 67 68 func (this *LRUCache) addNode(key int, value int) { 69 newNode := &lruNode{ 70 key: key, 71 value: value, 72 } 73 74 tmp := &this.node[hash(key)] 75 newNode.hnext = tmp.hnext 76 tmp.hnext = newNode 77 this.used++ 78 79 if this.tail == nil { 80 this.tail, this.head = newNode, newNode 81 return 82 } 83 this.tail.next = newNode 84 newNode.prev = this.tail 85 this.tail = newNode 86 } 87 88 func (this *LRUCache) delNode() { 89 if this.head == nil { 90 return 91 } 92 prev := &this.node[hash(this.head.key)] 93 tmp := prev.hnext 94 95 for tmp != nil && tmp.key != this.head.key { 96 prev = tmp 97 tmp = tmp.hnext 98 } 99 if tmp == nil { 100 return 101 } 102 prev.hnext = tmp.hnext 103 this.head = this.head.next 104 this.head.prev = nil 105 this.used-- 106 } 107 108 func (this *LRUCache) searchNode(key int) *lruNode { 109 if this.tail == nil { 110 return nil 111 } 112 113 // 查找 114 tmp := this.node[hash(key)].hnext 115 for tmp != nil { 116 if tmp.key == key { 117 return tmp 118 } 119 tmp = tmp.hnext 120 } 121 return nil 122 } 123 124 func (this *LRUCache) moveToTail(node *lruNode) { 125 if this.tail == node { 126 return 127 } 128 if this.head == node { 129 this.head = node.next 130 this.head.prev = nil 131 } else { 132 node.next.prev = node.prev 133 node.prev.next = node.next 134 } 135 136 node.next = nil 137 this.tail.next = node 138 node.prev = this.tail 139 140 this.tail = node 141 } 142 143 func hash(key int) int { 144 if hostbit { 145 return (key ^ (key >> 32)) & (LENGTH - 1) 146 } 147 return (key ^ (key >> 16)) & (LENGTH - 1) 148 }