【码不停题3.18】LRU缓存机制实现 双向链表+哈希map

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

进阶:

你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4

#include <map>
#include <list>
class LRUCache {
private:
    unordered_map<int, list<pair<int, int>>::iterator> mp;
    list<pair<int, int>> lt;
    int size;
public:
    LRUCache(int capacity) {
        size = capacity;
    }
    
    int get(int key) {
        if (mp.count(key)) {
            int result = mp[key]->second;
            lt.splice(lt.begin(), lt, mp[key]);
            return result;
        } else {
            return -1;
        }
    }
    
    void put(int key, int value) {
        if (mp.count(key)) {
            mp[key]->second = value;
            lt.splice(lt.begin(), lt, mp[key]);
        } else {
            lt.emplace_front(key,value);
            mp[key] = lt.begin();
            if (lt.size() > size) {
                mp.erase(lt.back().first);
                lt.pop_back();
            }
        }
    }
};

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

总结

  1. 对于关联容器,如map,set(以及multi类型)等,erase当前的迭代器iterator,仅仅会使当前的iterator失效,并不影响以后的内容,所以只要在进行删除前,预先保留下一个当前迭代器的递增值即可。这是因为关联类容器使用了红黑树实现,删除一个节点不会对其他节点造成影响。
    对于序列式容器,如 vector,deque等,删除当前节点会使后面的所有节点的迭代器失效。这是因为这类容器每次进行插入或者删除都会使之后的元素位置进行重新移动定位,致使之前的迭代器失效。
  2. void emplace_front (Args&&... args);
    Construct and insert element at beginning
    Inserts a new element at the beginning of the list, right before its current first element. This new element is constructed in place using args as the arguments for its construction.
    void push_front (const value_type& val);
    Inserts a new element at the beginning of the list, right before its current first element. The content of val is copied (or moved) to the inserted element.
  3. splice
    // entire list (1)	
    void splice (iterator position, list& x);
    // single element (2)	
    void splice (iterator position, list& x, iterator i);
    // element range (3)	
    void splice (iterator position, list& x, iterator first, iterator last);
    
    Transfers elements from x into the container, inserting them at position.
  4. .back()是最后一个 .end()是最后一个后的一个
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值