【发布时间】:2020-07-13 06:21:01
【问题描述】:
我可以使用列表和(散列)映射成功实现 LRU 缓存。我想知道为什么当我使用双端队列而不是列表时会出现错误行为。让我简要解释一下我的方法。
- 使用地图中的键查找值。该映射返回一个包含其值的列表或双端队列的迭代器。
- 应该更新迭代器 2.1。从地图和列表或双端队列中删除现有节点。 2.2.将一个新节点推入列表的前面,并且该映射还将新节点的键和迭代器作为值保存。
所以我的问题是:当我使用双端队列而不是列表时,为什么会得到错误的结果?我猜双端队列内部有一个块列表,它会产生问题。但是,我不确定根本原因。
这是一个可重现的代码。预期的结果是“9 29 9”,使用列表时我可以看到正确的答案。但是使用双端队列时返回错误的结果“9 29 29”。
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
#if 1
using List = deque<pii>;
#else
using List = list<pii>;
#endif
using ListIter = List::iterator;
using Map = unordered_map<int, ListIter>;
class LRUCache {
size_t capacity;
List lru_list;
Map map;
public:
LRUCache(size_t capacity) : capacity(capacity) {}
void put(int key, int value) {
Map::iterator miter = map.find(key);
promote(key, value, miter != map.end() ? miter->second
: (lru_list.size() == capacity) ? --lru_list.end() : lru_list.end());
}
int get(int key) {
Map::iterator miter = map.find(key);
if (miter == map.end()) return -1;
pii v = *(miter->second);
promote(v.first, v.second, miter->second);
return v.second;
}
void promote(int key, int value, ListIter iter) {
if (iter != lru_list.end()) lru_list.erase(iter);
lru_list.push_front({key, value});
map[key] = lru_list.begin();
}
};
void run(LRUCache& cache, vvi& vv) {
for (auto& e : vv) {
if (e.size() > 1) cache.put(e[0], e[1]);
else cout << cache.get(e[0]) << endl;
}
}
void test1() {
LRUCache cache(10);
vvi vv {
{10,27}, {8,10}, {6,29}, {1,9},
{1}, {6}, {1}
};
run(cache, vv);
}
int main() {
test1();
return 0;
}
【问题讨论】:
-
请将您的问题限制在 1 个主要问题上,而不是两个单独的问题
-
感谢您的反馈。我已经更新了我的问题。
-
您还需要minimal reproducible example 而不是外部链接
-
感谢您的友好评论。我添加了一个紧凑的可重现场景,而不是提供带有详细描述的链接。
标签: c++ list iterator deque c++-standard-library