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  }