LRC缓存算法详解

LRC缓存算法:

  • 初次见到这个算法的时候,自己比较的懵,这是啥?为什么算法还有这个?慢慢看了看,算了,咱还是看看其他的算法。所以一直将这个LRU算法一直放在旁边。最近看了看redis和mysql,都会有这个算法的身影,突然感觉这个算法还不错。于是花了些时间研究了一些,其实吧!也没啥。看能看着有点点多。第一次吓住了,可是当我理解他的思路之后就感觉正常了能接受了。

上代码

  • 可能乍一看,我去,代码这么多,我不看了。慢着!!!往下看,咱们分解讲一下。如果你还不理解,咱就是说:“这都是我的错,没有讲明白😄,但是咱们还是要好好的学习的,继续通过别的途径学习,加油⛽️”
package main

func main() {

}

//这里定义一个LRUCache的机构,后面主要操作的就是这里面的数据
type LRUCache struct {
	size       int  //缓存中节点个数
	capacity   int  //缓存中容量大小
	cache      map[int]*DLinkedNode  //声明一个map类型的缓存,key为int类型,通过key获取对应的value(value:是具体的数据)
	head, tail *DLinkedNode  //声明两个节点(头节点,为节点以供操作)
}

//DLinkedNode 定义一个节点
type DLinkedNode struct {
	key, value int             //该节点中的key和value
	prev, next *DLinkedNode    //该节点指向上一个和下一个节点的指针
}

//initDLinkedNode 初始化一个节点
func initDLinkedNode(key, value int) *DLinkedNode {
  //返回这个节点的key,value
	return &DLinkedNode{
		key:   key,
		value: value,
	}
}

//Constructor 实现lru的构造函数
func Constructor(capacity int) LRUCache {
  //实现LRU的构造函数,初始化一个可以使用的LRC
	l := LRUCache{
		cache:    map[int]*DLinkedNode{},
		head:     initDLinkedNode(0, 0),
		tail:     initDLinkedNode(0, 0),
		capacity: capacity,
	}
  //将头节点和尾节点的指针相互指向
	l.head.next = l.tail
	l.tail.prev = l.head
  //将完整的LRC返回
	return l
}

//获取节点数据
func (this *LRUCache) Get(key int) int {
  //先查看当前的缓存中有没有key对应的缓存
  //如果没有就返回:-1
	if _, ok := this.cache[key]; !ok {
		return -1
	}
  //如果有就返回对应的值,并将这个值移动到头部
	node := this.cache[key]
	this.moveToHead(node)
	return node.value
}

//添加节点
func (this *LRUCache) Put(key int, value int) {
   //先查看当前的缓存中有没有key对应的缓存
	if _, ok := this.cache[key]; !ok {
    //创建一个新的节点
		node := initDLinkedNode(key, value)
    //将节点数据加入缓存中
		this.cache[key] = node
    //将节点移到头部
		this.addToHead(node)
    //节点个数加一
		this.size++
    //判断当前缓存中节点的个数是否超过缓存的容量,如果超过就移除掉尾节点
		if this.size > this.capacity {
			removed := this.removeTail()
			delete(this.cache, removed.key)
			this.size--   //移除之后,对应的size减一
		}
	} else {
    //如果有就更新这个key对应的value,然后将节点移动到头部
		node := this.cache[key]
		node.value = value
		this.moveToHead(node)
	}
}

//添加一个节点的时候将节点添加到头部
func (this *LRUCache) addToHead(node *DLinkedNode) {
  //这是一个双向的节点,下面的操作实现向一个双向链表中插入一个节点,四个指向
  //前两行,将插入的节点,prev指向head,next指向next
	node.prev = this.head
	node.next = this.head.next
  //后两行,将head节点的next指向插入节点,将原来head指向的节点的prev指向当前节点
	this.head.next.prev = node
	this.head.next = node
}

//移除一个节点
func (this *LRUCache) removeNode(node *DLinkedNode) {
  //移除一个节点,将这个节点的上一个节点的next指向当前节点的下一个节点,将下一个节点的prev指向当前节点的前一个节点
	node.prev.next = node.next
	node.next.prev = node.prev
}

//将一个节点移动到头部
func (this *LRUCache) moveToHead(node *DLinkedNode) {
  //通过移除节点,然后将这个节点添加到头部的方式实现将一个节点移动到头部
	this.removeNode(node)
	this.addToHead(node)
}

//移除尾节点
func (this *LRUCache) removeTail() *DLinkedNode {
	node := this.tail.prev
	this.removeNode(node)
	return node
}

具备知识:

这道题我的解题思路主要是围绕着链表进行的,所以可能有的小伙伴没有接触数据结构,然后看起来迷迷糊糊的,而且感觉代码量太多了,所以就不想学了。其实不然,越是这样的代码也是考验一个人的学习能力,大家可以尝试去理解,如果不能理解链表(没有系统学习过链表的同学可能对于prev,next,head,tail之间的逻辑比较的混乱),就去学习一下数据结构中的链表这一块。我相信学习之后的你在看这道题就是捋清楚逻辑的问题了

学无止境,加油⛽️

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值