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.
pro:
实现一个LRU Cache,要求能根据key做get操作,返回其value;能对给出的key,value如果之前的key存在,则设置value;不存在则如果Cache的容量尚有多余,直接插入,否则要淘汰最近最少用的数据,再将其插入。无论是set还是get,都视这个数据是最新被使用过。
sol:
可以预见,删除插入比较多,要做到O(1),就需要使用链表,需要记录最后的节点(最旧的)以便删除,又需要将新节点或者最近访问的节点插入到表头后,因此需要双向链表。get的时候又需要O(1)定位,所以需要一个map,从key指向链表的节点。有了这两个数据结构就OK了~!
trick:
双向链表的删除和插入操作是基础啊~!!分别影响两条线和四条线。
code:
struct ListNodee
{
int key;
int val;
ListNodee *next;
ListNodee *pre;
ListNodee(int x,int y):key(x),val(y),next(NULL),pre(NULL){}
};
class LRUCache{
private:
int capacity;
map<int,ListNodee*> mymap;
ListNodee *root;
ListNodee *lastone;
int current;
public:
LRUCache(int capacity) {
this->capacity = capacity;
this->mymap.clear();
this->root = new ListNodee(0,0);
this->lastone = root;
this->current = 0;
}
int get(int key) {
if(mymap.find(key)==mymap.end()) return -1;
else
{
ListNodee* temp = mymap[key];
makeTop(root,temp);
return temp->val;
}
}
void deletion(ListNodee *root,ListNodee *mynode)
{
//delete from map
map<int,ListNodee*>::iterator it;
it = mymap.find(mynode->key);
mymap.erase(it);
if(mynode->next==NULL) this->lastone = mynode->pre;
this->current--;
mynode->pre->next = mynode->next;
if(mynode->next!=NULL)//forgot added!!!!!!!
mynode->next->pre = mynode->pre;//forgot added!!!!!!!
}
void makeTop(ListNodee *root,ListNodee *mynode)
{
deletion(root,mynode);
insert(this->root,mynode);
}
void insert(ListNodee *root,ListNodee *mynode)
{
this->current++;
mynode->pre = root;
mynode->next = root->next;
if(root->next!=NULL)
root->next->pre = mynode;
root->next = mynode;
if(mynode->next == NULL) this->lastone = mynode;//forgot added!!!!!!!
mymap[mynode->key] = mynode;
}
void set(int key, int value) {
if(mymap.find((key))!=mymap.end())
{
ListNodee *temp = mymap[key];
temp->val = value;
makeTop(root,temp);
}else
{
ListNodee *newnode = new ListNodee(key,value);
if(this->current<this->capacity)
{
insert(this->root,newnode);
}else
{
//remove oldest,insert new,remove in map,update variables
deletion(this->root,this->lastone);
insert(this->root,newnode);
}
}
}
};