元月's blog 元月's blog
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多

元月

临渊羡鱼,不如退而结网
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多
  • 基础

  • 数据结构

    • 链表的基本操作:查找、删除
    • 链表的高级操作:链表的反转、合并、拆分
    • 链表的特殊状态:相交链表、回文链表、环形链表
    • 数组篇:双指针技巧
    • 数组篇:前缀和数组和差分数组
    • 数据结构与算法--跳表
    • 数据结构与算法--LRU算法
      • 一、简介
      • 二、LRU算法的代码实现
        • 2.1、双链表的节点类
        • 2.2、双链表的实现类
        • 2.3、put方法逻辑
        • 2.4、完整实现
    • 数据结构与算法--LFU算法
  • 网络

  • 操作系统

  • 计算机网络
  • 数据结构
元月
2022-12-03
目录

数据结构与算法--LRU算法

# 数据结构与算法--LRU算法

# 一、简介

LRU 的全称是 Least Recently Used(最近最少使用),是一种缓存淘汰策略,它是根据时间维度来选择将要淘汰的元素,即删除掉最长时间没被访问的元素据。它的底层是 哈希表 + 双链表 实现的,查找和添加的时间复杂度都是O(1),Java中的LinkedHashMap就是这样的一种数据结构。

剑指 Offer II 031. 最近最少使用缓存 (opens new window)

# 二、LRU算法的代码实现

# 2.1、双链表的节点类

class DLinkedNode{//双链表节点类
        int key,val;
        DLinkedNode pre,next;
        public DLinkedNode(int _key,int _val){
            this.key = _key;
            this.val = _val;
        }
 }
1
2
3
4
5
6
7
8

# 2.2、双链表的实现类

class DLinkedList{//双链表
       DLinkedNode head,tail;//链表首尾结点

       public DLinkedList(){
           this.head = new DLinkedNode(-1,-1);
           this.tail = new DLinkedNode(-1,-1);
           head.next = tail;
           tail.pre = head;
       }

       public void addToHead(DLinkedNode node){//将节点添加到头部
           node.pre = head;
           node.next = head.next;
           head.next.pre = node;
           head.next = node;
       }

       public void moveToHead(DLinkedNode node){//将某个访问后的节点添加到头部
           removeNode(node);
           addToHead(node);
       }

       public void removeNode(DLinkedNode node){//删除某个节点
           node.pre.next = node.next;
           node.next.pre = node.pre;
       }

       public DLinkedNode removeTail(){//删除尾部结点
           DLinkedNode res = tail.pre;
           removeNode(res);
           return res;
       }

   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 2.3、put方法逻辑

public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if(node == null){
            //创建新节点
            DLinkedNode newNode = new DLinkedNode(key,value);
            //哈希表加入结点
            cache.put(key,newNode);
            //结点addToHead
            linkedList.addToHead(newNode);
            size++;
            if(size > capacity){
                //删除尾部结点
                DLinkedNode tail = linkedList.removeTail();
                //哈希表删除结点
                cache.remove(tail.key);
                size--;
            }
        }else{
            node.val = value;
            //结点moveToHead
            linkedList.moveToHead(node);
        }
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 2.4、完整实现

class LRUCache {

    private Map<Integer,DLinkedNode> cache;//哈希表缓存

    private DLinkedList linkedList;//双链表

    private int size;//链表size
    private int capacity;//链表容量

    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        this.cache = new HashMap<>();
        this.linkedList = new DLinkedList();
    }
    
    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if(node == null) return -1;
        //节点moveToHead
        linkedList.moveToHead(node);
        return node.val;
    }
    
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if(node == null){
            //创建新节点
            DLinkedNode newNode = new DLinkedNode(key,value);
            //哈希表加入结点
            cache.put(key,newNode);
            //结点addToHead
            linkedList.addToHead(newNode);
            size++;
            if(size > capacity){
                //删除尾部结点
                DLinkedNode tail = linkedList.removeTail();
                //哈希表删除结点
                cache.remove(tail.key);
                size--;
            }
        }else{
            node.val = value;
            //结点moveToHead
            linkedList.moveToHead(node);
        }
    }

   class DLinkedList{//双链表

       DLinkedNode head,tail;//链表首尾结点

       public DLinkedList(){
           this.head = new DLinkedNode(-1,-1);
           this.tail = new DLinkedNode(-1,-1);
           head.next = tail;
           tail.pre = head;
       }

       public void addToHead(DLinkedNode node){//将节点添加到头部
           node.pre = head;
           node.next = head.next;
           head.next.pre = node;
           head.next = node;
       }

       public void moveToHead(DLinkedNode node){//将某个访问后的节点添加到头部
           removeNode(node);
           addToHead(node);
       }

       public void removeNode(DLinkedNode node){//删除某个节点
           node.pre.next = node.next;
           node.next.pre = node.pre;
       }

       public DLinkedNode removeTail(){//删除尾部结点
           DLinkedNode res = tail.pre;
           removeNode(res);
           return res;
       }

   }

    class DLinkedNode{//双链表节点类
        int key,val;
        DLinkedNode pre,next;
        
        public DLinkedNode(int _key,int _val){
            this.key = _key;
            this.val = _val;
        }

    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#数据结构
数据结构与算法--跳表
数据结构与算法--LFU算法

← 数据结构与算法--跳表 数据结构与算法--LFU算法→

最近更新
01
otter二次开发-支持按目标端主键索引Load数据
08-03
02
mvnw简介
06-21
03
gor流量复制工具
06-03
更多文章>
Theme by Vdoing | Copyright © 2022-2024 元月 | 粤ICP备2022071877号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式