LRU算法(刷题记录)

LRU算法是一种常用的缓存淘汰策略,它基于“最近最少使用”的原则。文章介绍了LRU的核心思想,即使用哈希链表作为数据结构,结合了哈希表的快速查找和链表的顺序操作。LRUCache类的实现包括get和put方法,以及如何维护节点的顺序和容量管理。
摘要由CSDN通过智能技术生成

LRU算法:

LRU缓存淘汰算法就是一种常用策略。LRU的全称是Least Recently Used,也就是说我们认为最近使用过的数据应该是[有用的],很久都没有用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。

LRU算法设计:

1.显然cache中的元素必须有时序,以区分最近使用的和久未使用的数据,当容量满了之后要删除最久未使用的那个元素腾出位置。

2.我们要在cache中快速找某个key是否已存在并得到对应的val;

3.每次访问cache中的某个key,需要将这个元素变为最近使用的,也就是说cache要支持在任意位置快速插入和删除元素。

那么,什么数据结构同时符合上述条件呢?哈希表查找快,但数据无固定顺序;链表有顺序之分,插入删除快,但是查找慢。所以结合一下,形成一种新的数据结构:哈希链表。

LRU缓存算法的核心数据结构就是哈希链表,双向链表和哈希表的结合体。

 代码:

class Node {
public:
    int key, val;
    Node* prev, *next;
    Node() : key(0), val(0), prev(nullptr), next(nullptr) {} 
    Node(int k, int v) : key(k), val(v), prev(nullptr), next(nullptr) {}
};

class DoubleList {
public:
    DoubleList() {
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->prev = head;
        sz = 0;
    }

    void addNode(Node* node) {
        node->next = tail;
        node->prev = tail->prev;
        tail->prev->next = node;
        tail->prev = node;
        sz++;
    }

    Node* removeNode() {
        if (head->next == tail) {
            return nullptr;
        }
        Node* rmNode = head->next;
        head->next = rmNode->next;
        rmNode->next->prev = head;
        sz--;
        return rmNode;
    }

    void getNode(Node* node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        sz--;
    }

    int getSize() {return sz;}

private:
    Node* head;
    Node* tail;
    int sz;
};

class LRUCache {
public:
    LRUCache(int capacity) {
        cap = capacity;
        list = new DoubleList();
    }
    
    int get(int key) {
        if (mp.count(key)) {
            Node* cur = mp[key];
            list->getNode(cur);
            list->addNode(cur);
            return cur->val;
        }
        return -1;
    }
    
    void put(int key, int value) {
        if (mp.count(key)) {
            Node* cur = mp[key];
            cur->val = value;
            list->getNode(cur);
            list->addNode(cur);
        } else {
            Node* node = new Node(key, value);
            mp[key] = node;
            list->addNode(node);
            if (cap < list->getSize()) {
                Node* rmNode = list->removeNode();
                mp.erase(rmNode->key);
            }
        }
    }
private:
    unordered_map<int, Node*> mp;
    DoubleList* list;
    int cap;
};

/**
 * 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);
 */

参考学习:算法就像搭乐高:带你手撸 LRU 算法 :: labuladong的算法小抄

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值