最近面试遇到不少自己不会的面试题,为了防止以后再遇到,所以记录下来
这次遇到的是LRU算法的实现,LRU是用于内存管理的一种页面置出算法,意为最近最少使用,用于将内存中经常不适用的页面置出内存,放入到外存或者对换区,使得其他可使用的页面进入内存
主要的操作是get/put,这篇实现完全照抄于博客:博客
所有的代码都没怎么改变,主要是我将自己的理解写在上面并做了一些测试,感兴趣的可以去大佬的博客,我这里主要是做一下记录,不是原创,如果有涉及到侵权请作者联系删除,下面贴代码:
class LRUCache {
public:
LRUCache(int capacity) :cap_(capacity), size_(0) {}
int get(int key) {
if (key2pos_.find(key) != key2pos_.end()) { //说明存在
put(key, key2pos_[key]->second); //这一步实际上是将最近访问得结点移到队列头部 见下put函数
return key2pos_[key]->second; //返回对应得头部
}
return -1;
}
void put(int key, int value) {
if (key2pos_.find(key) != key2pos_.end()) { //若结点已经存在
data_.erase(key2pos_[key]); //替换为最新的 后面会移动到list首部
--size_;
}
else if (size_ > cap_) { //超过容量则删除最后的结点
key2pos_.erase(data_.back().first); //删除
data_.pop_back();
--size_;
}
data_.push_front({ key, value }); //链表首部
key2pos_[key] = data_.begin(); //映射
++size_;
}
void print() {
for (auto &w : data_) {
cout << w.first << ":" << w.second << endl; //打印的结果是最新插入的结果在最前面
}
cout << endl;
}
private:
int cap_;
int size_;
list<pair<int, int>> data_; //list存储
unordered_map<int, list<pair<int, int>>::iterator> key2pos_; //哈希映射
};
一些测试结果:
int main() {
LRUCache lru(10);
lru.put(1, 2);
lru.put(3, 4);
lru.put(5, 6);
lru.print(); //原始打印出应该是按插入的逆序
lru.get(1); //获取一个key-value由于 是最近被使用所以应该移动到头部
lru.print(); //将上面的get的key-value最先打印 其他顺序不变
}
主要使用list来存储结点,最近使用的和get后的移动到头部,最少使用的放在尾部,使用unordered_map进行位置映射
从结果看到,进行put后,最先打印的是最后放进去的,进行一次get操作,get到的key-value就放在头部