传送门
此题让我们实现一个LRU的模板类。本题较简便且高效的写法是维护一个std::list
和一个std::unordered_map
。
std::list 与 std::unordered_map 中存放的内容
std::list
中存放各key,类型为K。链表中各键码存放的顺序是按照访问顺序存放的。
std::unordered_map
中以key为第一维,第二维为一个pair
,其first
和second
分别为:
first
: 该key对应的value。
second
:该key在std::list
中的迭代器方便访问。
为方便,下面用“链表”来指代std::list
,用“哈希表”来指代std::unordered_map
。
各操作实现
insert
操作:用哈希表判断该键是否已经存在。若存在,先在链表中删除该key,然后再新加一个该key到链表尾部,并更新在哈希表中的value和链表的迭代器。若不存在,则直接加至链表尾部,并在哈希表中插入该key,伴随着对应的value和链表迭代器。
get
操作:直接从哈希表中获得其value即可。代码实现未检测该key是否存在,严谨来说应该加上异常处理。
contains
操作:直接在哈希表中查询是否存在该key即可。
vis
操作:用哈希表判断该键是否存在。若不存在,则本操作无效。否则,将该键从链表中删除,然后再将其加至链表尾部,并更新哈希表中对应链表迭代器。
pop
操作:判断是否整个容器已经为空。若为空,则本操作无效。否则,将链表头部元素从链表中删除,并在哈希表中删除对应键值信息。
remove
操作:用哈希表判断该键是否存在。若不存在,则本操作无效。否则,将该键从链表中删除,并在哈希表中删除对应键值信息。
empty
操作:哈希表或链表判空即可。
size
操作:取哈希表或链表大小即可。
clear
操作:清空哈希表和链表即可。
时间复杂度
各操作基于对链表和哈希表的修改。期望复杂度均为$O(1)$。
参考代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include <list> #include <unordered_map>
template <typename K, typename V> class LRU { private: typedef typename std::list<K>::iterator listIter; typedef typename std::unordered_map<K, std::pair<V, listIter>>::iterator unorderedMapIter; std::list<K> lst; std::unordered_map<K, std::pair<V, listIter>> mp;
public: void insert(const K &key, const V &value) { unorderedMapIter it = mp.find(key); if (it == mp.end()) { lst.emplace_back(key); mp.insert(std::make_pair(key, std::make_pair(value, --lst.end()))); } else { lst.erase(it->second.second); lst.emplace_back(key); it->second = std::make_pair(value, --lst.end()); } }
V get(const K &key) { return mp[key].first; }
bool contains(const K &key) { return mp.count(key) == 1; }
void vis(const K &key) { unorderedMapIter it = mp.find(key); if (it != mp.end()) { lst.erase(it->second.second); lst.emplace_back(key); it->second.second = --lst.end(); } }
void pop() { if (!lst.empty()) { mp.erase(lst.front()); lst.pop_front(); } }
void remove(const K &key) { unorderedMapIter it = mp.find(key); if (it != mp.end()) { lst.erase(it->second.second); mp.erase(it); } }
bool emtpy() { return lst.empty(); }
unsigned long long size() { return lst.size(); } void clear() { lst.clear(); mp.clear(); } };
|