LRUCache

LRUCache往往用于排列最近被”修改或访问过的热门的“数据,属缓存类目,是我个人认为链表系中,和跳表共同组成链表系的两个最大的实体


其组成,就是一个双向链表,同时有一个hash表实现快速的由key找到对应节点,当有读取操作时,如果能够找到对应key的节点,不仅符合节点value,还会把该key对应节点放在链表头部位置,当修改或插入操作时,如hash表可以找到该key的节点即update,并不是仅更新value这样,而是先删除该节点,然后创建一个新的节点并放在头部,插入也是会将新创建的节点作为链表头,体现了最新被操作的key的数据总是被更新在链表头部。


LRUCache自定义链表的容量限制,当插入新节点时发现已满,则要删除尾部节点,再创建新节点并置于头部,意味着代码需要维护tail节点。

LRUCache往往实践中被用于缓存,是一个重要的数据结构。


代码:

#include <iostream>
#include <unordered_map>


template<class T> struct Node {
    T key;
    T val;
    Node<T> *next;
    Node<T> *prev;
    Node(T _key, T _val):key(_key), val(_val), next(nullptr), prev(nullptr) {}
};

template<class T> class LruCache {
    Node<T> *head;
    Node<T> *tail;
    int size;
    int maxsize;
    std::unordered_map<T, Node<T> *> nodemap;

    void Insert (T key, T val) {
        Node<T> *newnode = new Node<T>(key, val);
        if (!head) {
            head = newnode;
            tail = newnode;
            head->next = tail->next = nullptr;
            head->prev = tail->prev = nullptr;
            return;
        }
        newnode->next = head;
        newnode->prev = head->prev;
        head->prev = newnode;
        head = newnode;
        nodemap[key] = newnode;
    }

    void Delete (Node<T> *node) {
        if (node) {
            Node<T> *prev = node->prev;
            Node<T> *next = node->next;
            if (prev) {
                prev->next = next;
            }
            if (next) {
                next->prev = prev;
            }
            if (node == tail) {
                tail = prev;
            }
            nodemap.erase(node->key);
            delete node;
            node = nullptr;
        }
    }
    
public:
    LruCache (int _maxsize):size(0), maxsize(_maxsize), head(nullptr), tail(nullptr) {}
    ~LruCache () {
        Node<T> *cur = head;
        while (cur) {
            Node<T> *next = cur->next;
            delete cur;
            cur = next;
        }
        size = 0;
        nodemap.clear();
    }

    void Set (T key, T val) {
        if (nodemap.find(key) == nodemap.end()) {
            if (size < maxsize) {
                Insert(key, val);
                ++size;
            } else {
                Delete(tail);
                Insert(key, val);
            }
        } else {
            Node<T> *node = nodemap.find(key)->second;
            Delete(node);
            Insert(key, val);
        }
    }

    bool Get (T key, T &val) {
        if (nodemap.find(key) != nodemap.end()) {
            Node<T> *node = nodemap.find(key)->second;
            val = node->val;
            Delete(node);
            Insert(key, val);
            return true;
        }

        return false;
    }

    void Show () {
        Node<T> *cur = head;
        while (cur) {
            std::cout << cur->key << "\t";
            cur = cur->next;
        }
        std::cout << std::endl;
    }
};

int main () {
    LruCache<int> lrc(20);

    for (int i = 0; i < 100; i++) {
        lrc.Set(i, i);
        lrc.Show();
        int v;
        lrc.Get(i - 1, v);
        lrc.Show();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值