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.h
#include <map>
#include <iostream>
using namespace std;
struct ListNode
{
int key;
int value;
ListNode* next;
ListNode* pre;
ListNode(int key,int val):key(key),value(val){next = NULL; pre = NULL;}
};
class LRUCache
{
public:
LRUCache(int capacity);
~LRUCache();
int get(int key);
void set(int key,int value);
private:
ListNode* head;
ListNode* end;
int capacity;
map<int, ListNode*> cache;
};
LRU.cpp
#include "LRU.h"
LRUCache::LRUCache(int capacity)
{
this->capacity = capacity;
//初始化头尾指针
head = new ListNode(0,0);
end = head;
}
LRUCache::~LRUCache()
{
cache.clear();
//析构
while(head!=NULL)
{
end = head;
head = head->next;
delete end;
}
}
int LRUCache::get(int key)
{
map<int , ListNode*>::iterator iTemp = cache.find(key);
if(iTemp == cache.end())
return -1;
if(iTemp -> second != head->next)
{
if(iTemp->second == end)
{
//如果当前指针为尾指针,把尾指针向前一位
end = end->pre;
end -> next =NULL;
}
else
{
//将iTemp的前后节点相连
iTemp -> second ->next->pre = iTemp->second->pre;
iTemp -> second ->pre ->next = iTemp->second->next;
}
//将iTemp插入head之后
iTemp -> second -> next = head -> next;
iTemp -> second -> pre = head;
head -> next = iTemp -> second;
iTemp -> second -> next->pre = iTemp ->second;
}
//测试输出
ListNode* t = head->next;
while(t!=NULL)
{
cout<<"("<<t->key<<","<<t->value<<")\t";
t = t->next;
}
cout<<endl;
return iTemp -> second -> value;
}
void LRUCache::set(int key, int value)
{
if(capacity == 0)
return ;
map<int , ListNode*>::iterator iTemp = cache.find(key);
//key不存在
if(iTemp == cache.end())
{
ListNode* plnNew = new ListNode(key,value);
if(cache.size() == 0)
end = plnNew;
//新节点加入头部
plnNew -> next = head->next;
plnNew -> pre = head;
head -> next = plnNew;
if(plnNew -> next !=NULL)
plnNew -> next ->pre = plnNew;
//删除尾节点以及map中的pair
if(cache.size() >= capacity)
{
ListNode* plnTemp = end;
end = end -> pre;
end->next = NULL;
cache.erase(plnTemp->key);
delete plnTemp;
}
//插入新pair
pair<int,ListNode*> pNew(key,plnNew);
cache.insert(pNew);
}
else
{
iTemp->second->value = value;
//如果当前节点不是头结点
if(iTemp -> second != head->next)
{
if(iTemp->second == end)
{
//若当前节点为尾节点
end = end->pre;
end -> next =NULL;
}
else
{
//将当前节点的前后节点相连
iTemp -> second ->next->pre = iTemp->second->pre;
iTemp -> second ->pre ->next = iTemp->second->next;
}
//将当前节点插入头部
iTemp -> second -> next = head -> next;
iTemp -> second -> pre = head;
head -> next = iTemp -> second;
iTemp -> second -> next->pre = iTemp ->second;
}
}
//测试输出
ListNode* t = head->next;
while(t!=NULL)
{
cout<<"("<<t->key<<","<<t->value<<")\t";
t = t->next;
}
cout<<endl;
}
已AC 316ms
注意:
1、找到的节点为尾节点时,需要更新尾指针(这点可以改进为:把end改为tail作为一个尾指针 下述方法将提到)
方法二:改成尾指针
#include <map>
#include <iostream>
using namespace std;
struct ListNode
{
int key;
int value;
ListNode* next;
ListNode* pre;
ListNode(int key,int val):key(key),value(val){next = NULL; pre = NULL;}
};
class LRUCache
{
public:
LRUCache(int capacity);
~LRUCache();
int get(int key);
void set(int key,int value);
private:
ListNode* head;
ListNode* tail;
int capacity;
map<int, ListNode*> cache;
};
#include "LRU.h"
LRUCache::LRUCache(int capacity)
{
this->capacity = capacity;
//初始化头尾指针
head = new ListNode(0,0);
tail = new ListNode(0,0);
head -> next = tail;
tail -> pre = head;
cache.clear();
}
LRUCache::~LRUCache()
{
cache.clear();
//析构
while(head!=NULL)
{
tail = head;
head = head->next;
delete tail;
}
}
int LRUCache::get(int key)
{
map<int , ListNode*>::iterator iTemp = cache.find(key);
if(iTemp == cache.end())
return -1;
if(iTemp -> second != head->next)
{
//将iTemp的前后节点相连
iTemp -> second ->next->pre = iTemp->second->pre;
iTemp -> second ->pre ->next = iTemp->second->next;
//将iTemp插入head之后
iTemp -> second -> next = head -> next;
iTemp -> second -> pre = head;
head -> next = iTemp -> second;
iTemp -> second -> next->pre = iTemp ->second;
}
//测试输出
ListNode* t = head->next;
while(t!=NULL)
{
cout<<"("<<t->key<<","<<t->value<<")\t";
t = t->next;
}
cout<<endl;
return iTemp -> second -> value;
}
void LRUCache::set(int key, int value)
{
if(capacity == 0)
return ;
map<int , ListNode*>::iterator iTemp = cache.find(key);
//key不存在
if(iTemp == cache.end())
{
ListNode* plnNew = new ListNode(key,value);
//新节点加入头部
plnNew -> next = head->next;
plnNew -> pre = head;
head -> next = plnNew;
plnNew -> next ->pre = plnNew;
//删除尾节点以及map中的pair
if(cache.size() >= capacity)
{
ListNode* plnTemp = tail -> pre;
tail -> pre = tail ->pre -> pre;
tail->pre->next = tail;
cache.erase(plnTemp->key);
delete plnTemp;
}
//插入新pair
pair<int,ListNode*> pNew(key,plnNew);
cache.insert(pNew);
}
else
{
iTemp->second->value = value;
//如果当前节点不是头结点
if(iTemp -> second != head->next)
{
//将当前节点的前后节点相连
iTemp -> second ->next->pre = iTemp->second->pre;
iTemp -> second ->pre ->next = iTemp->second->next;
//将当前节点插入头部
iTemp -> second -> next = head -> next;
iTemp -> second -> pre = head;
head -> next = iTemp -> second;
iTemp -> second -> next->pre = iTemp ->second;
}
}
//测试输出
ListNode* t = head->next;
while(t!=NULL)
{
cout<<"("<<t->key<<","<<t->value<<")\t";
t = t->next;
}
cout<<endl;
}
已AC 340ms