动态地维护容量一定的hash表,访问频率高的保留,反之则视剩余容量决定是否保存,
一般的hash表直接记录各个键值对就行了,但多了容量有限的情况,要做一点改动。这里可以通过双端链表来保存键值对,key被访问了就移动到链表头部,对应“访问频率高”的情况,而原本的hash表就不能简单的存储键值对了,此时应该记录链表节点的指针,毕竟链表中已经记录了键值对。为什么用双端链表,因为移动结点方便。
思路厘清了剩余的就是基本的实现了,就是双端链表和hash表的操作
#include <vector>
#include <unordered_map>
#include <iostream>
using namespace std;
/*
lru:用空间换时间
双端链表 key/value
unordered_hashmap key和结点指针
get
set
维护:容量限制
其实储存用hashmap已经够了,key和value,双端链表是为了记录使用频率
*/
struct DNode {
DNode* pre, * next;
int key, value;
DNode(int key = 0, int value = 0) :key(key), value(value), pre(NULL), next(NULL) {}
};
class LRUCache {
unsigned int capacity;
unordered_map<int, DNode*>mp;
DNode* Head, * Tail; //头尾节点不储存数据
public:
explicit LRUCache(int a) :capacity(a), Head(new DNode), Tail(new DNode) {
Head->next = Tail; Tail->pre = Head;
}
~LRUCache() {
DNode* node = Head;
while (node != Tail) {
node = node->next;
delete node->pre;
}
delete Tail;
}
int get(int k) {
if (mp.count(k)) {
MoveDNode2Head(mp[k]); //mp[k]是指针,通过下标访问
return mp[k]->value;
}
else return -1;
}
void MoveDNode2Head(DNode* node) {
if (!node || node->pre == Head)return;
removeDNode(node);
addDNode2Head(node);
}
void removeDNode(DNode* node) {
if (!node)return;
node->pre->next = node->next;
node->next->pre = node->pre;
}
void addDNode2Head(DNode* node) {
if (!node || node->pre == Head)return;
node->next = Head->next;
Head->next->pre = node;
Head->next = node;
node->pre = Head;
}
void set(int k, int v) {
if (!mp.count(k)) {
DNode* node = new DNode(k, v);
mp[k] = node;
addDNode2Head(node);
if (mp.size() > capacity) {
DNode* last = Tail->pre;
mp.erase(last->key);
removeDNode(last);
delete last;
}
}
else {
mp[k]->value = v;
MoveDNode2Head(mp[k]);
}
}
};
class Solution {
public:
/**
* lru design
* @param operators int整型vector<vector<>> the ops
* @param k int整型 the k
* @return int整型vector
*/
vector<int> LRU(vector<vector<int> >& operators, int k) {
// write code here
LRUCache lru(k);
vector<int> res;
for (auto vec : operators) {
if (vec[0] == 1) {
lru.set(vec[1], vec[2]);
}
else {
res.push_back(lru.get(vec[1])); //只获得get的键值?
}
}
return res;
}
};
void test() {
vector<vector<int> > vv = { {1,1,1},{1,2,2},{1,3,2},{2,1},{1,4,4},{2,2} };
Solution s;
vector<int> vec = s.LRU(vv, 10);
for (auto i : vec)cout << i << " " << endl;
}