我的 LRU 怎么了?我是否错误地使用了 std::deque?

问题描述

我对此感到非常沮丧,现在我仍然完全不知道为什么我会出错。 所以我正在做 LRU 实现如下:

#include <iostream>
#include <unordered_map>
#include <deque>
#include <list>

using namespace std;

class LRUCache {
public:
    LRUCache(int capacity) : cap(capacity) {
        cache.clear();
        pos_map.clear();
    }
    void check_recent() {
        cout << "recent: ";
        for (auto it : cache)
            cout << it << " ";
        cout << endl;
    }
    int get(int key) {
        cout << "get: " << key << " ; ";
        auto it = pos_map.find(key);
        if (it != pos_map.end()) {
            cache.erase(it->second.second);
            cache.push_front(key);
            pos_map[key].second = cache.begin();
            check_recent();
            return pos_map[key].first;
        } 
        check_recent();
        return -1;
    }
    
    void put(int key,int value) {
        cout << "put: " << key << "," << value << " ; ";
        auto it = pos_map.find(key);
        if (it != pos_map.end()) {
            pos_map[key].first = value;
            cache.erase(it->second.second);
            cache.push_front(key);
            pos_map[key].second = cache.begin();
        } else {
            cache.push_front(key);
            if (cache.size() > cap) {
                int remove = cache.back();
                cache.pop_back();
                pos_map.erase(remove);
            }
            pos_map[key] = make_pair(value,cache.begin());
        }
        
        check_recent();
        return ;
    }
private:
    int cap;
    deque<int> cache; // deque of keys
    unordered_map<int,pair<int,deque<int>::iterator>> pos_map;
    // <key,<value,iter>>
};

int main()
{
    cout<<"Hello World\n";
    LRUCache* obj = new LRUCache(10);
    obj->put(10,13);
    obj->put(3,17);
    obj->put(6,11);
    obj->put(10,5);
    obj->put(9,10);
    obj->get(13);
    obj->put(2,19);
    obj->get(2);
    obj->get(3);
    obj->put(5,25);
    obj->put(9,22);
    obj->put(5,5);
    obj->put(1,13);
    obj->put(9,12);
    return 0;
}

然后我得到以下输出

Hello World
put: 10,13 ; recent: 10 
put: 3,17 ; recent: 3 10 
put: 6,11 ; recent: 6 3 10 
put: 10,5 ; recent: 10 6 3 
put: 9,10 ; recent: 9 10 6 3 
get: 13 ; recent: 9 10 6 3 
put: 2,19 ; recent: 2 9 10 6 3 
get: 2 ; recent: 2 9 10 6 3 
get: 3 ; recent: 3 2 9 10 6 
put: 5,25 ; recent: 5 3 2 9 10 6 
put: 9,22 ; recent: 9 5 3 2 10 6 
put: 5,5 ; recent: 5 9 3 2 10 6 
put: 1,13 ; recent: 1 5 9 3 2 10 6 
put: 9,12 ; recent: 9 1 "9" 3 2 10 6 

这个故障“9”花了我一个小时才弄清楚原因,但还是徒劳。但问题是,如果我将代码中的所有 std::deque 更改为 std::list,结果与我的期望相同:

put: 9,12 ; recent: 9 1 "5" 3 2 10 6 

那么 std::deque::erase 到底是怎么回事?我做错什么了吗? 任何人都可以指导我或给我一些线索吗? 非常感谢

解决方法

那么 std::deque::erase 到底是怎么回事?我做错了什么吗?

您有两个数据结构,其中一个映射到另一个的迭代器:

    deque<int> cache; // deque of keys
    unordered_map<int,pair<int,deque<int>::iterator>> pos_map;

如果迭代器要出队,则 the invalidation rules of erase 状态

所有迭代器和引用都无效,除非被擦除的元素位于容器的末尾或开头,在这种情况下,只有迭代器和对被擦除元素的引用无效。

然而,for list 我们有

对已擦除元素的引用和迭代器无效。其他引用和迭代器不受影响。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...