zoukankan      html  css  js  c++  java
  • LRU算法的简易实现

    LRU全称Least Recently Used,也就是 最近最少使用的意思,是一种内存管理算法,该算法最早应用于 Linux操作系统。
    这个算法基于一种假设:长期不被使 用的数据,在未来被用到的几率也不大。因此,当数据所占内存达 到一定阈值时,我们要移除掉最近最少被使用的数据。
    LRU算法中,使用了一种有趣的数据结构,这种数据结构叫作哈希 链表。

    我们都知道,哈希表是由若干个Key-Value组成的。在“逻辑”上,这些 Key-Value是无所谓排列顺序的,谁先谁后都一样。

    在哈希链表中,这些Key-Value不再是彼此无关的存在,而是被一个链 条串了起来。每一个Key-Value都具有它的前驱Key-Value、后继Key- Value,就像双向链表中的节点一样。


    依靠哈希链表的有序性,我们可以把 Key-Value按照最后的使用时间进行排序。

    LRU算法的基本思路

    1. 假设使用哈希链表来缓存用户信息,目前缓存了4个用户,这4个用户
      是按照被访问的时间顺序依次从链表右端插入的。

    2. 如果这时业务方访问用户5,由于哈希链表中没有用户5的数据,需要
      从数据库中读取出来,插入到缓存中。此时,链表最右端是最新被访问
      的用户5,最左端是最近最少被访问的用户1。

    3. 接下来,如果业务方访问用户2,哈希链表中已经存在用户2的数据,
      这时我们把用户2从它的前驱节点和后继节点之间移除,重新插入链表
      的最右端。此时,链表的最右端变成了最新被访问的用户2,最左端仍
      然是最近最少被访问的用户1

    1. 接下来,如果业务方请求修改用户4的信息。同样的道理,我们会把
      用户4从原来的位置移动到链表的最右侧,并把用户信息的值更新。这
      时,链表的最右端是最新被访问的用户4,最左端仍然是最近最少被访
      问的用户1。

    2. 后来业务方又要访问用户6,用户6在缓存里没有,需要插入哈希链表
      中。假设这时缓存容量已经达到上限,必须先删除最近最少被访问的数
      据,那么位于哈希链表最左端的用户1就会被删除,然后再把用户6插入
      最右端的位置。

    代码实现

    package algorithm
    
    
    type lruNode struct {
       key  interface{}
       data interface{}
       next *lruNode
       prev *lruNode
    }
    
    type LruCache struct {
       limit int
       head  *lruNode
       end   *lruNode
       value map[interface{}]*lruNode
    }
    
    
    func (l *LruCache) Get(key interface{}) (interface{},bool) {
       a,b := l.value[key]
       return a,b
    }
    
    
    func (l *LruCache) Add(key interface{}, value interface{}) {
       if len(l.value) >= l.limit {
          oldKey := l.removeNode(l.head)
          delete(l.value, oldKey)
       }
       node := &lruNode{data: value, key: key}
       if l.end != nil {
          l.end.next = node
          node.prev = l.end
          node.next = nil
       }
       l.end = node
       if l.head == nil {
          l.head = node
       }
       l.value[key] = node
    }
    
    func (l *LruCache) removeNode(node *lruNode) interface{} {
       if node == l.head && node == l.end {
    
    
       } else if node == l.end {
          l.end = l.end.prev
          l.end.next = nil
       } else if node == l.head {
          l.head = l.head.next
          l.head.prev = nil
       } else {
          node.prev.next = node.next
          node.next.prev = node.prev
       }
       return node.key
    }
    
    
    func NewLruCache(cap int) *LruCache {
       return &LruCache{limit: cap, value: make(map[interface{}]*lruNode)}
    }
    
  • 相关阅读:
    Starting Tomcat v7.0 Server at localhost (2)hasencountered a problemServer Tomcat v7.0 Server at localhost (2)failed tostart
    如何获取系统当前时间
    解决TextEncoder 和 TextDecoder在IE下不兼容 vue 用iconv-lite插件代替 解决中文乱码问题
    vue 读取本地TXT GBK编码文件
    HTML常用标签和属性大全
    echarts中的个性化设计
    MySQL常用优化指南和思路
    微服务框架 Service Mesh
    spring boot actuator监控
    关于Swagger @ApiModel 返回内容注释不显示问题
  • 原文地址:https://www.cnblogs.com/lisq/p/12808123.html
Copyright © 2011-2022 走看看