LRU算法 缓存淘汰算法

 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

  1. 新数据插入到链表头部;
  2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
  3. 当链表满的时候,将链表尾部的数据丢弃。

 

  1. 最开始时,内存空间是空的,因此依次进入A、B、C是没有问题的
  2. 当加入D时,就出现了问题,内存空间不够了,因此根据LRU算法,内存空间中A待的时间最为久远,选择A,将其淘汰
  3. 当再次引用B时,内存空间中的B又处于活跃状态,而C则变成了内存空间中,近段时间最久未使用的
  4. 当再次向内存空间加入E时,这时内存空间又不足了,选择在内存空间中待的最久的C将其淘汰出内存,这时的内存空间存放的对象就是E->B->D
package main

import "fmt"

type LRUCache struct {
	capacity int
	mapItem  map[int]*Node
	head     *Node
	tail     *Node
}

type Node struct {
	key   int
	value int
	pre   *Node
	next  *Node
}

func (n *Node) String() string {
	return fmt.Sprintf("key:%d  ---  value:%d\n", n.key, n.value)
}

func Constructor(capacity int) LRUCache {

	head := &Node{
		key:   -1,
		value: -1,
		pre:   nil,
		next:  nil,
	}

	tail := &Node{
		key:   -1,
		value: -1,
		pre:   nil,
		next:  nil,
	}

	head.next = tail
	tail.pre = head

	lru := LRUCache{
		capacity: capacity,
		mapItem:  make(map[int]*Node, capacity),
		head:     head,
		tail:     tail,
	}
	return lru
}

func (this *LRUCache) Get(key int) int {
	if v, ok := this.mapItem[key]; ok {
		this.MoveToFront(v)
		return v.value
	}
	return -1
}

func (this *LRUCache) Put(key int, value int) {
	if this.Get(key) != -1 {
		node := this.mapItem[key]
		node.value = value
		this.MoveToFront(node)
	} else {
		if len(this.mapItem) < this.capacity {
			node := &Node{
				key:   key,
				value: value,
				pre:   nil,
				next:  nil,
			}
			this.AddToFront(node)
			this.mapItem[key] = node

		} else {
			delNode := this.tail.pre
			delete(this.mapItem, delNode.key)
			this.mapItem[key] = delNode
			delNode.key = key
			delNode.value = value
			this.MoveToFront(delNode)
		}
	}
}

func (this *LRUCache) AddToFront(node *Node) {
	node.next = this.head.next
	this.head.next.pre = node
	this.head.next = node
	node.pre = this.head
}

func (this *LRUCache) MoveToFront(node *Node) {
	this.DelNode(node)
	this.AddToFront(node)
}

func (this *LRUCache) DelNode(node *Node) {
	if node == this.head || node == this.tail {
		return
	}
	node.next.pre = node.pre
	node.pre.next = node.next
}

func (this *LRUCache) dump(s string) {
	fmt.Println(s)
	node := this.head.next
	for node != this.tail {
		fmt.Print(node)
		node = node.next
	}
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * obj := Constructor(capacity);
 * param_1 := obj.Get(key);
 * obj.Put(key,value);
 */

func main() {
	this := Constructor(2)
	this.Put(1, 1)
	this.dump("111111111111111111")
	this.Put(2, 2)
	this.dump("2222222222222222")

	fmt.Println(this.Get(1))
	this.Put(3, 3)
	this.dump("333333333333333")
	fmt.Println(this.Get(2))
	this.Put(4, 4)
	this.dump("4444444444444")
	fmt.Println(this.Get(1))
	fmt.Println(this.Get(3))
	fmt.Println(this.Get(4))
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值