当前位置:   article > 正文

链表-LRU缓存

链表-LRU缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRU是Least Recently Used的缩写,意为“最近最少使用”。LRU是一种常用的缓存淘汰策略,用于管理缓存中的数据。

举个例子,你从一堆书中找出自己想要看的书,读完之后一般是放在最上面;如果你又从其他地方拿了一本书读完之后,打算放入这堆书中,如果这堆书中还有同名书,只是年份不同,那么就用这本书进行替换,如果没有同名书,由于“空间”不够使用,只能将最底下的书移走,再放入这本书

LRU缓存算法的基本思想是:当缓存空间不足时,优先淘汰最近最少使用的数据,以便为新数据腾出空间。具体来说,LRU算法会维护一个有序列表,列表中的元素按照访问时间从新到旧排列。每当缓存命中时,就将命中的数据移动到列表的头部,每当缓存缺失时,就将新数据插入到列表的头部,并将列表尾部的数据淘汰掉。

LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。

void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。

如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

由于题目要求O(1)复杂度,采取双链表,每个节点都是一本书;使用哈希来快速查找书籍

先创建节点Node

struct Node{
    int _key;
    int _value;
    Node* _next;
    Node* _prev;
    Node(int key, int value): _key(key), _value(value), _next(nullptr), _prev(nullptr){}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

刚开始时,使用一个哨兵节点

class LRUCache {
private:
    Node* _dummy;
    int _capacity;
    unordered_map<int, Node*> _map;
    
public:
    LRUCache(): _dummy(new Node(-1, -1)), _capacity(0){
        _dummy->_next = _dummy;
        _dummy->_prev = _dummy;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

实现查找书

    Node* get_node(int key)//查找书
    {
        auto it=_map.find(key);
        if(it==_map.end())//没找到
            return nullptr;
        auto node=it->second;//找到了
        remove(node);//从书堆中取出
        insert_to_head(node);//放在书顶
        return node;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现将书从书堆中移除

    void remove(Node* node)//从书堆中移除
    {
        node->_prev->_next = node->_next;
        node->_next->_prev = node->_prev;
    }
  • 1
  • 2
  • 3
  • 4
  • 5

实现将书放入书顶

    void insert_to_head(Node* node)//放入书顶
    {
        node->_next = _dummy->_next;
        node->_prev = _dummy;
        _dummy->_next->_prev = node;
        _dummy->_next = node;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实现取书get功能

    int get(int key)
    {
        auto node=get_node(key);//查找这本书
        return node?node->_value:-1;
    }
  • 1
  • 2
  • 3
  • 4
  • 5

实现放入put功能

    void put(int key, int value)
    {
        auto node = get_node(key);
        if(node)//书堆中已经存在,进行替换
        {
            node->_value=value;
            return;
        }
        _map[key]=node=new Node(key, value);
        insert_to_head(node);//独一份,放入书顶
        if(_map.size()>_capacity)
        {
            auto node=_dummy->_prev;
            remove(node);
            _map.erase(node->_key);
            delete node;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

完整代码

struct Node{
    int _key;
    int _value;
    Node* _next;
    Node* _prev;
    Node(int key, int value): _key(key), _value(value), _next(nullptr), _prev(nullptr){}
};

class LRUCache {
private:
    Node* _dummy;
    int _capacity;
    unordered_map<int, Node*> _map;

    void remove(Node* node)//从书堆中移除
    {
        node->_prev->_next = node->_next;
        node->_next->_prev = node->_prev;
    }

    void insert_to_head(Node* node)//放入书顶
    {
        node->_next = _dummy->_next;
        node->_prev = _dummy;
        _dummy->_next->_prev = node;
        _dummy->_next = node;
    }

    Node* get_node(int key)//查找书
    {
        auto it=_map.find(key);
        if(it==_map.end())//没找到
            return nullptr;
        auto node=it->second;//找到了
        remove(node);//从书堆中取出
        insert_to_head(node);//放在书顶
        return node;
    }

public:
    LRUCache(): _dummy(new Node(-1, -1)), _capacity(0){
        _dummy->_next = _dummy;
        _dummy->_prev = _dummy;
    }

    int get(int key)
    {
        auto node=get_node(key);//查找这本书
        return node?node->_value:-1;
    }

    void put(int key, int value)
    {
        auto node = get_node(key);
        if(node)//书堆中已经存在,进行替换
        {
            node->_value=value;
            return;
        }
        _map[key]=node=new Node(key, value);
        insert_to_head(node);//独一份,放入书顶
        if(_map.size()>_capacity)
        {
            auto node=_dummy->_prev;
            remove(node);
            _map.erase(node->_key);
            delete node;
        }
    }
};
  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/491634
推荐阅读
相关标签
  

闽ICP备14008679号