Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
题目的意思是设置页面置换算法(LRU):最近最少使用,实现两种操作,
1、get(key)获取关键字对应的值value,如果key不存在返回-1
2、set(key,value),设置关键字key对应的值为value,如果不存在key,需要增加一个key,设值为value
通过上面描述的,首先思考如何存储cache,用什么样的数据结构,还要描述出LRU的特点,所以用到双向链表,把最近使用的节点放在最前面,
为了便于插入和删除节点,还需要定义头结点和尾节点。
下面是数据结构定义:
struct node {
node* pre;
int key;
int value;
node* next;
node(int k, int v):key(k),value(v),pre(NULL),next(NULL) {};
};
每个节点都有前向指针和后向指针
使用map<int,node*> mapa,存储key与节点之间的一一映射关系,便于查找节点,用mapa.find(key)直接查找
操作set函数的时候,如果插入一个节点到头之后,需要统计一下节点个数size,如果size大于capacity,则需要删除最后一个节点
这样就符合LRU的特点了。
class LRUCache {
map<int, node*> mp;
node* head;
node* tail;
int size;
int capacity;
public:
LRUCache(int c) {
if (c < 1)return;
head = new node(0, 0);
tail = new node(0, 0);
head->next = tail;
tail->pre = head;
mp.clear();
size = 0;
capacity = c;
}
int get(int k) {
map<int, node*>::iterator it = mp.find(k);
if (it != mp.end()) {
node* cur = (*it).second;
cur->pre->next = cur->next;
cur->next->pre = cur->pre;
putToHead(cur);
return cur->value;
} else
return -1;
}
void set(int k, int val) {
if (capacity < 1)return;
map<int, node*>::iterator it = mp.find(k);
if (it != mp.end()) {//find
node* cur = (*it).second;
cur->pre->next = cur->next;
cur->next->pre = cur->pre;
cur->value = val;
putToHead(cur);
} else {//not find
node* tmp = new node(k,val);
putToHead(tmp);
mp[k] = tmp;
if (size < capacity) {//size < capacity
size++;
} else {//size >= capacity
node* deltmp = tail->pre;
tail->pre = deltmp->pre;
deltmp->pre->next = tail;
it = mp.find(deltmp->key);
mp.erase(it);
delete deltmp;
}
}
}
void putToHead(node* cur)
{
cur->next = head->next;
cur->pre = head;
cur->next->pre = cur;
head->next = cur;
}
};