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.
此题需要注意几个点:
1. get(key),如果key在缓存中,则要将key所在单元设置为最近访问的状态
2. set(key,value)也是作为最近访问的单元,如果key所表示的单元已经存在缓存中,且原来的value值与该value值不相等,则要将原来的value更新为该value值
思路:
拿到此题时,首先考虑是使用数组还是使用链表作为缓存的数据结构。由于缓存经常需要对节点增删查改,如果使用数组,添加删除节点效率较低,于是决定使用链表。然后考虑是使用单链表还是使用双向链表,还是使用单向循环链表,最后决定使用双向链表,用单向循环链表也可以。
代码如下:
struct node{
int key;
int value;
struct node *next, *pre;
};
struct head_ptr{
struct node *head;
int num;
};
class LRUCache{
public:
LRUCache(int capacity) {
this->capacity = capacity;
lru_list = new head_ptr;
lru_list->head = NULL;
lru_list->num = 0;
}
int get(int key) {
if(NULL == lru_list->head) return -1;
struct node *p = lru_list->head;
do{
if(p->key == key){
//key是最后一个节点
if(p->next == lru_list->head)
return p->value;
//key是头节点,因为是循环链表只需将第二节点改为头节点就行
if(p == lru_list->head){
lru_list->head = p->next;
return p->value;
}
//key是链表中中间的节点
p->pre->next = p->next;
p->next->pre = p->pre;
lru_list->head->pre->next = p;
p->pre = lru_list->head->pre;
lru_list->head->pre = p;
p->next = lru_list->head;
return p->value;
}
p = p->next;
}while(p!=NULL && p!=lru_list->head);
return -1;
}
void set(int key, int value) {
int res = get(key);
if(res != -1)
{
struct node *p = lru_list->head->pre;
p->value = value;
return;
}
if(lru_list->num >= capacity)
{
// cout << "key out of: " << key <<endl;
struct node *p = lru_list->head;
p->key = key;
p->value = value;
lru_list->head = p->next;
return;
}
struct node *p = new node;
p->key = key;
p->value = value;
if(lru_list->head == NULL){
if(capacity <= 0)
{
delete p;
return;
}
p->next = p;
p->pre = p;
lru_list->head = p;
lru_list->num++;
return;
}
if(lru_list->num< capacity){
// cout << "key: " << key <<endl;
lru_list->head->pre->next = p;
p->pre = lru_list->head->pre;
lru_list->head->pre = p;
p->next = lru_list->head;
lru_list->num++;
return;
}
}
//测试用
void printKey()
{
struct node *p = lru_list->head;
cout <<"result: ";
do{
cout << p->key << " ";
p=p->next;
}while(p && p!=lru_list->head);
cout << endl;
}
private:
int capacity;
struct head_ptr *lru_list;
};