LRU代码实现

LRU:最久未使用置换原则
均以3个内存块举例。

在这里插入图片描述

FIFO:先进先出
在这里插入图片描述
LRU算法代码实现:

/*
双链表:最底端是最久未使用的
哈希表:通过缓存数据的键映射到其在双向链表中位置
        对hash表做put和get:

给LRU的cache用map
    初始化
    get(LRU核心):获取链表中该页号存的值,如果不存在,则返回-1,如果存在,则把它移动到链表顶部,因为算使用一次
    put:(LRU核心):只要是put过的,都要移动到头顶,且分为当前节点是否已经存在,不存在则创建新节点加入到头部,如果链表过长,则删除尾
    借助map:根据页号寻找链表节点
    借助DLinkNode:把当前内存块串联起来
*/


class DLinkNode
{
public:
    int key, val;
    DLinkNode* pre;
    DLinkNode* nxt;
    DLinkNode(): key(0), val(0), pre(nullptr), nxt(nullptr){}
    DLinkNode(int _key, int _val):key(_key), val(_val), pre(nullptr), nxt(nullptr){}

};

class LRUCache {
    // 根据存入数据,找对应链表
    unordered_map<int, DLinkNode*> cache;
    DLinkNode* head;
    DLinkNode* tail;
    // 缓存块数量和当前大小
    int size;
    int capacity;
public:                                 // 内(参)
    LRUCache(int capacity):capacity(capacity), size(0)
    {
        head = new DLinkNode();
        tail = new DLinkNode();
        head->nxt = tail;
        tail->pre = head;
    }

    // 存:获取当前页面的值,如果存在就获取且让它到链表顶部
    int get(int key) 
    {
        // 页面号不存在则返回-1
        if (cache.find(key) == cache.end())
            return -1;
        // key存在,先哈希定位,再移动到头
        DLinkNode* node =  cache[key];
        moveToHead(node);
        return node->val;
    }
    // 找值,且移动到首位
    void put(int key, int val)
    {
        // 不存在该key,则创建新节点
        if (cache.find(key) == cache.end())
        {
            DLinkNode* node = new DLinkNode(key, val);
            cache[key] = node;
            // 单独的节点加到头部
            addToHead(node);
            ++size;
            // 容量超了,就删除尾部
            if (size > capacity)
            {
                DLinkNode* tail = removeTail();
                cache.erase(tail->key);
                delete tail;
                --size;
            }
        }
        // 存在则获取
        else
        {
            // 如果key存在,map中获取该节点,移动到头
            DLinkNode* node = cache[key];
            // 不必做判断也可
            if (node->val != val)
                node->val = val;
            moveToHead(node);
        }
    }

    // 已存在与链表中的节点移动到头部,利用删除和插入顶部两个函数
    void moveToHead(DLinkNode* node)
    {
        // 两个顺序无所谓
        removeNode(node);
        // 新节点,放到头部
        addToHead(node);
    }
    // 删除链表节点
    void removeNode(DLinkNode* node)
    {
        // 当前节点的左右两链表节点链接做改变
        node->pre->nxt = node->nxt;
        node->nxt->pre = node->pre;
    }
    // 把一个节点,放到头部:不论是否已在链表中
    void addToHead(DLinkNode* node)
    {
        // 动头和当前
        node->nxt = head->nxt;
        node->pre = head;
        head->nxt->pre = node;
        head->nxt = node;
    }
    // 删除链表尾部
    DLinkNode* removeTail()
    {
        DLinkNode* node = tail->pre;
        removeNode(node);
        return node;
    }
};

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

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值