前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LRU缓存淘汰机制C++实现

LRU缓存淘汰机制C++实现

原创
作者头像
evenleo
修改2020-10-13 14:22:46
7640
修改2020-10-13 14:22:46
举报
文章被收录于专栏:C++的沉思C++的沉思

前言

LRU 是 Least Recently Used 的简写,字面意思是最近最少使用。

通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被撑满。

代码实现

#ifndef _LRU_CACHE_H_
#define _LRU_CACHE_H_

#include <unordered_map>
/*
* LRU是Least Recently Used的简写,字面意思是最近最少使用,通常用于缓存淘汰策略
* 维护一个双向链表,并用无序关联式容器unordered_map存储链表的节点
*/
template <typename Key, typename Value>
class LRUCache {
private:
    struct Node {
        Key key;
        Value value;
        Node* prev;
        Node* next;
        Node(Key k, Value v)
            : key(k)
            , value(v)
            , prev(nullptr)
            , next(nullptr)
        {
        }
    };

public:
    LRUCache(size_t capacity)
        : capacity_(capacity)
        , head_(nullptr)
        , tail_(nullptr)
    {
    }
    ~LRUCache()
    {
        while (head_ != nullptr) {
            Node* next = head_->next;
            delete head_;
            head_ = next;
        }
    }

    /*
    * @brief 获取缓存值
    * 根据key获取value,不存在返回nullptr
    * 存在,则在双向链表中删除该节点,再将节点添加到表头
    */
    Value* get(Key key)
    {
        auto it = datas_.find(key);
        if (it == datas_.end()) {
            return nullptr;
        } else {
            Node* node = datas_[key];
            remove(node);
            appendHead(node);
            return &node->value;
        }
    }

    /*
    * @brief 将键值对放进缓存中
    * 缓存已存在,更新value,并在双向链表中删除该节点,再将节点添加到表头
    * 不存在,创建节点node,如果当前缓存大小小于缓存容量,直接将节点添加到
    * 表头即可,否则将双向链表的尾结点在关联式容器hashMap中删除,然后在双
    * 向链表中也删除尾节点,最后将新节点添加到表头和hashMap中
    */
    void put(Key key, Value value)
    {
        auto it = datas_.find(key);
        if (it != datas_.end()) {
            Node* node = it->second;
            node->value = value;
            remove(node);
            appendHead(node);
        } else {
            Node* node = new Node(key, value);
            if (datas_.size() < capacity_) {
                appendHead(node);
                datas_[key] = node;
            } else {
                datas_.erase(tail_->key);
                Node* delNode = tail_;
                remove(delNode);
                delete delNode;
                appendHead(node);
                datas_[key] = node;
            }
        }
    }

private:
    /*
    * 将节点添加到双向链表的头部
    */
    void appendHead(Node* node)
    {
        if (head_ == nullptr)
            head_ = tail_ = node;
        else {
            node->next = head_;
            head_->prev = node;
            head_ = node;
        }
    }

    /*
    * 在双向链表删除node节点,但不销毁节点,主要是为了其他方法可以通用
    */
    void remove(Node* node)
    {
        if (head_ == tail_) {
            head_ = tail_ = nullptr;
        } else if (head_ == node) {
            head_ = node->next;
            head_->prev = nullptr;
        } else if (tail_ == node) {
            tail_ = node->prev;
            tail_->next = nullptr;
        } else {
            node->prev->next = node->next;
            node->next->prev = node->prev;
        }

        node->next = nullptr;
        node->prev = nullptr;
    }

private:
    size_t capacity_; // 缓存容量
    Node* head_; // 双向链表的头结点
    Node* tail_; // 双向链表的尾结点
    std::unordered_map<int, Node*> datas_; // 无序关联式容器
};

#endif

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 代码实现
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档