一、LRUCache.h
#pragma once
#include <iostream>
#include <list>
#include <optional>
#include <unordered_map>
template<typename K, typename V>
class LRUCache {
public:
LRUCache(size_t cap) : cap_(cap) {}
bool put(const K& k, const V& v) {
auto itr = index_.find(k);
if (itr != index_.end()) {
items_.splice(items_.begin(), items_, itr->second);
return true;
}
if (cap_ == items_.size()) {
index_.erase(items_.back().first);
items_.pop_back();
}
items_.emplace_front(k, v);
index_.emplace(k, items_.begin());
return true;
}
std::optional<V> get(const K& k) {
auto itr = index_.find(k);
if (itr == index_.end()) {
return {};
}
items_.splice(items_.begin(), items_, itr->second);
return itr->second->second;
}
template<typename C>
void forEach(const C& callback) const {
for(auto& [k,v] : items_) {
callback(k, v);
}
}
private:
size_t cap_;
std::list<std::pair<K, V>> items_;
std::unordered_map<K, typename std::list<std::pair<K,V>>::iterator> index_;
};
二、test.cpp
#include "LRUCache.h"
template<typename C>
void printlnCache(const C& cache) {
cache.forEach([](auto& k, auto& v){
std::cout << k << "=>" << v << " ";
});
std::cout << std::endl;
}
int main() {
LRUCache<std::string, double> cache(3);
cache.put("London", 8.4);
cache.put("Toronto", 2.5);
cache.put("Sydney", 5.2);
cache.put("chen", 5.2);
printlnCache(cache);
std::optional<double> res = cache.get("Toronto");
std::cout << "res=" << res.value() << std::endl;
printlnCache(cache);
}
编译
g++ -std=c++17 test.cpp -I ./ -o test
三、参考
https://www.nextptr.com/tutorial/ta1576645374/stdlist-splice-for-implementing-lru-cache