LRU(近期最少使用算法)C++实现源码

写在前面

今天一同学去公司实习面试,面试官要求手写LRU算法,有些懵。在这里想写篇博客给他作为参考,同时也给大家作为参考。

LRU(最近最少使用算法)

LRU是CPU cache中n-way的一种替换规则(对cache不了解的可以查看https://en.wikipedia.org/wiki/CPU_cache),当有新成员加入时,它需要替换近期最少被使用的cache line。

  • 双向链表+哈希表
    这种方式比较常见,如图所示:
    LRU(近期最少使用算法)C++实现源码_第1张图片
    新数据或击中的数据放到链表头部,表示最近使用的数据,如果链表满,从尾部淘汰数据。但只用链表会存在一个问题,击中数据的时间复杂度为O(n),每次需要遍历链表,所以引入哈希表,时间复杂度降到O(1),以空间换时间。
#include 
#include 
#include    
using namespace std;  
struct Element
{
    int key;
    int value;
    Element(int k, int v):key(k), value(v){}
};
class LRUCache {
private:
    list m_list;
    unordered_map<int, list::iterator> m_map;
    int m_capacity;
public:
    LRUCache(int capacity) {
        m_capacity = capacity;
    }

    int get(int key) {
        if (m_map.find(key) == m_map.end())
            return -1;
        else
        {
            //将元素放入链表头部
            m_list.splice(m_list.begin(), m_list, m_map[key]);
            m_map[key] = m_list.begin();
            return m_list.begin()->value;
        }
    }

    void put(int key, int value) {
        assert(m_capacity > 0);
        if (m_map.find(key) != m_map.end())
        {   //更value
            m_map[key]->value = value;
            //将元素放入链表头部
            m_list.splice(m_list.begin(), m_list, m_map[key]);
            m_map[key] = m_list.begin();
        }
        else if (m_capacity == m_list.size())
        {
            m_map.erase(m_list.back().key);
            m_list.pop_back();
            m_list.push_front(Element(key, value));
            m_map[key] = m_list.begin();
        }
        else
        {
            m_list.push_front(Element(key, value));
            m_map[key] = m_list.begin();
        }
    }
};

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

你可能感兴趣的:(数据结构,算法)