FJUTOJ-3682 LRU算法的實現2 (鏈表+哈希)
[FJUTOJ-3682] LRU算法的實現2
傳送門
此題讓我們實現一個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)\)。
參考代碼實現
#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()); } } // If Key doesn't exist, this will create one <Key, zero> 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(); } };
FJUTOJ-3682 LRU算法的實現2 (鏈表+哈希)