1. 程式人生 > >FJUTOJ-3682 LRU算法的實現2 (鏈表+哈希)

FJUTOJ-3682 LRU算法的實現2 (鏈表+哈希)

return mov pla 實現 清空 line rst 我們 his

[FJUTOJ-3682] LRU算法的實現2

傳送門

此題讓我們實現一個LRU的模板類。本題較簡便且高效的寫法是維護一個std::list和一個std::unordered_map

std::list 與 std::unordered_map 中存放的內容

std::list中存放各key,類型為K。鏈表中各鍵碼存放的順序是按照訪問順序存放的

std::unordered_map中以key為第一維,第二維為一個pair,其firstsecond分別為:

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 (鏈表+哈希)