lru算法php,LRU 算法

LRU 最近最少使用算法,LRU算法主要用于缓存淘汰。主要目的就是把最近最少使用的数据移除内存,以加载其他数据。

原理

添加元素时,放到链表头

缓存命中,将元素移动到链表头

缓存满了之后,将链表尾的元素删除

LRU算法实现

可以用一个双向链表保存数据

支持两个方向,每个结点不止有一个后继指针 next 指向后面的结点,还有一个前驱指针 prev 指向前面的结点

双向链表要比单链表占用更多的内存空间。虽然两个指针比较浪费存储空间,但可以支持双向遍历,这样也带来了双向链表操作的灵活性

双向链表可以支持 O(1) 时间复杂度的情况下找到前驱结点,正是这样的特点,也使双向链表在某些情况下的插入、删除等操作都要比单链表简单、高效

使用hash实现O(1)的访问

源码简单注释:

package lru

import "container/list"

// Cache 结构体,定义lru cache 不是线程安全的

type Cache struct {

// 数目限制,0是无限制

MaxEntries int

// 删除时, 可以添加可选的回调函数

OnEvicted func(key Key, value interface{})

ll *list.List // 使用链表保存数据

cache map[interface{}]*list.Element // map

}

// Key 是任何可以比较的值 http://golang.org/ref/spec#Comparison_operators

type Key interface{}

type entry struct {

key Key

value interface{}

}

// 创建新的cache 对象

func New(maxEntries int) *Cache {

return &Cache{

MaxEntries: maxEntries,

ll: list.New(),

cache: make(map[interface{}]*list.Element),

}

}

// 添加新的值到cache里

func (c *Cache) Add(key Key, value interface{}) {

if c.cache == nil {

c.cache = make(map[interface{}]*list.Element)

c.ll = list.New()

}

if ee, ok := c.cache[key]; ok {

// 缓存命中移动到链表的头部

c.ll.MoveToFront(ee)

ee.Value.(*entry).value = value

return

}

// 添加数据到链表头部

ele := c.ll.PushFront(&entry{key, value})

c.cache[key] = ele

if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {

// 满了删除最后访问的元素

c.RemoveOldest()

}

}

// 从cache里获取值.

func (c *Cache) Get(key Key) (value interface{}, ok bool) {

if c.cache == nil {

return

}

if ele, hit := c.cache[key]; hit {

// 缓存命中,将命中元素移动到链表头

c.ll.MoveToFront(ele)

return ele.Value.(*entry).value, true

}

return

}

// 删除指定key的元素

func (c *Cache) Remove(key Key) {

if c.cache == nil {

return

}

if ele, hit := c.cache[key]; hit {

c.removeElement(ele)

}

}

// 删除最后访问的元素

func (c *Cache) RemoveOldest() {

if c.cache == nil {

return

}

ele := c.ll.Back()

if ele != nil {

c.removeElement(ele)

}

}

func (c *Cache) removeElement(e *list.Element) {

c.ll.Remove(e)

kv := e.Value.(*entry)

delete(c.cache, kv.key)

if c.OnEvicted != nil {

c.OnEvicted(kv.key, kv.value)

}

}

// cache 缓存数

func (c *Cache) Len() int {

if c.cache == nil {

return 0

}

return c.ll.Len()

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值