最近最少使用数据结构(LRU)

抛开算法刷题的角度,LRU数据结构可根据访问时间远近自动排序,在有些场景下还是很有用的,如统计用户活跃度,API调用热力图分析,缓存块管理等。下面基于c++模板提供一个通用的LRU类,以供参考。

cpp 复制代码
#include <functional>
#include <list>
#include <unordered_map>
#include <utility>

template<typename Key, typename Val>
class LRUCache {
public:
    using value_deinit_callback = std::function<void(Key, Val)>;
    static void value_release_handle(Key k, Val v)
    {}
    //如果Val是指针类型,可在func中指定指针清理动作
    LRUCache(int capacity, const value_deinit_callback& func = value_release_handle) :
        m_capacity(capacity), m_value_deinit(func)
    {}
    ~LRUCache()
    {
        for (auto pairs : m_cached_list)
        {
            if (m_value_deinit.operator bool())
                m_value_deinit(pairs.first, pairs.second);
        }
        m_hash_table.clear();
        m_cached_list.clear();
    }
    Val get(const Key& key) {
        auto iter = m_hash_table.find(key);
        if (iter == m_hash_table.end())
            return Val{};
        auto& liter = iter->second;
        auto pairs = *liter;
        m_cached_list.erase(liter);
        liter = m_cached_list.insert(m_cached_list.end(), pairs);
        return liter->second;
    }

    void put(Key key, Val val) {
        auto iter = m_hash_table.find(key);
        if (iter != m_hash_table.end())
        {
            auto pairs = *iter->second;
            pairs.second = val;
            m_cached_list.erase(iter->second);
            iter->second = m_cached_list.insert(m_cached_list.end(),pairs);
        }
        else
        {
            if (m_cached_list.size() >= m_capacity)
            {
                auto& pairs = m_cached_list.front();
                auto& fkey = pairs.first;
                auto& fval = pairs.second;
                auto it = m_hash_table.find(fkey);
                if (it != m_hash_table.end())
                {
                    m_value_deinit(fkey, fval);
                    m_hash_table.erase(it);
                }
                m_cached_list.pop_front();
            }
            m_hash_table.insert(std::make_pair(key, m_cached_list.insert(m_cached_list.end(), std::make_pair(key, val))));
        }
    }
private:
    int m_capacity;
    value_deinit_callback m_value_deinit;
    std::unordered_map<Key, typename std::list<std::pair<Key, Val>>::iterator> m_hash_table;
    std::list<std::pair<Key, Val>> m_cached_list;
};
相关推荐
linff91110 小时前
hot 100 技巧题
数据结构·算法·leetcode
jf加菲猫10 小时前
条款21:优先选用std::make_unique、std::make_shared,而非直接new
开发语言·c++
scx2013100410 小时前
20251019状压DP总结
c++
程序新视界10 小时前
详解MySQL两种存储引擎MyISAM和InnoDB的优缺点
数据库·后端·mysql
追逐时光者11 小时前
一个基于 .NET 8 + Vue3 实现的极简 RABC 权限管理系统
后端·.net
AI科技星11 小时前
接近光速运动下的光速不变性:基于张祥前统一场论的推导与验证
数据结构·人工智能·经验分享·算法·计算机视觉
m0_7482402511 小时前
C++ 游戏开发示例:简单的贪吃蛇游戏
开发语言·c++·游戏
Summer_Uncle11 小时前
【C++学习】指针
c++·学习
勇闯天涯&波仔11 小时前
verilog阻塞赋值和非阻塞赋值的区别
后端·fpga开发·硬件架构·硬件工程
lang2015092812 小时前
Spring Boot Actuator深度解析与实战
java·spring boot·后端