LRU Cache Implementation

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

The cache is initialized with a positive capacity.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

Test case:

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

/**
 * Author sesiria, 2019
 * LRU Cache implementation by double linklist and unordered_map(hash table)
 */ 
#include <algorithm>
#include <iostream>
#include <unordered_map>

using namespace std;

class LRUCache
{
private:
    struct Linklist
    {
        int key;
        int val;
        Linklist *next;
        Linklist *prev;
        Linklist(int k, int n) : key(k), val(n), next(nullptr), prev(nullptr) {}
    };

    unordered_map<int, Linklist *> table;
    Linklist *head; // virtual header.
    Linklist *tail; // virtual tailer node.
    int theCapacity;

    // private method.
    void removeFromList(Linklist *node)
    {
        // cut the node from list
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

    void insertToHeader(Linklist *node)
    {
        node->next = head->next;
        node->next->prev = node;

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

public:
    LRUCache(int capacity)
    {
        theCapacity = capacity;
        head = new Linklist(0, 0);
        tail = new Linklist(0, 0);
        head->next = tail;
        tail->prev = head;
    }

    ~LRUCache()
    {
        delete head;
        delete tail;
    }

    int get(int key)
    {
        auto iter = table.find(key);

        if (iter == table.end())
            return -1;
        else
        {
            Linklist *node = iter->second;
            removeFromList(node);
            insertToHeader(node);
            return node->val;
        }
    }

    void put(int key, int value)
    {
        auto iter = table.find(key);
        // the key is already existed.
        if (iter != table.end())
        {
            Linklist *node = iter->second;
            node->val = value;
            removeFromList(node);
            insertToHeader(node);
        }
        else
        {
            // the LRU cache is full, we remove the last element.
            if (table.size() == theCapacity)
            {
                Linklist *node = tail->prev;
                table.erase(node->key);
                removeFromList(node);
                delete node;
            }

            Linklist *newNode = new Linklist(key, value);
            insertToHeader(newNode);
            table.insert(make_pair(key, newNode));
        }
    }
};

int main()
{
    LRUCache cache(2);
    int result;

    cache.put(1, 1);
    cache.put(2, 2);
    result = cache.get(1);      // returns 1
    cache.put(3, 3);            // evicts key 2
    result = cache.get(2);      // returns -1 (not found)
    cache.put(4, 4);            // evicts key 1
    result = cache.get(1);      // returns -1 (not found)
    result = cache.get(3);      // returns 3
    result = cache.get(4);      // returns 4

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章