使用双向链表+map,实现O(1)时间内的get和set
需要注意的是:
1. set时更新tail
size为0时更新头部
size为capacity时删除头部并且更新头部
2. get时更新节点到tail的位置,同时如果是节点是头部的话要更新头部
附上代码:
class LRUCache{
struct Node{
int key;
int val;
Node* next;
Node* pre;
Node(int k, int v)
{
key = k;
val = v;
next = pre = NULL;
}
};
Node * head;
Node * tail;
int size;
int cap;
map<int, Node*> keyMap;
public:
LRUCache(int capacity) {
head = tail = NULL;
cap = capacity;
size = 0;
keyMap = map<int, Node*>();
}
~LRUCache(){
while (head)
{
Node * deleteNode = head;
head = head->next;
delete deleteNode;
}
}
Node * getNode(int key)
{
if (keyMap.find(key) == keyMap.end())
return NULL;
Node* foundNode = keyMap[key];
if (size == 1 || foundNode == tail) return foundNode;
if (foundNode == head)//size > 1, foundNode->next is not NULL
head = foundNode->next;
//remove foundNode from list
foundNode->next->pre = foundNode->pre;
if (foundNode->pre) foundNode->pre->next = foundNode->next;
//update tail
tail->next = foundNode;
foundNode->pre = tail;
tail = tail->next;
//update foundNode
foundNode->next = NULL;
return foundNode;
}
int get(int key) {
Node * foundNode = getNode(key);
if (foundNode) return foundNode->val;
else return -1;
}
void set(int key, int value) {
Node * foundNode = getNode(key);//put Node to the front of list
//if key exists, update value
if (foundNode)
{
foundNode->val = value;
return;
}
//if key not exists, create Node
Node * newNode = new Node(key, value);
keyMap[key] = newNode;
if (size == 0)
tail = head = newNode;
else
{
tail->next = newNode;
newNode->pre = tail;
tail = tail->next;
}
size++;
//check if need delete
if (size <= cap) return;
Node * deleteNode = head;
head = head->next;
head->pre = NULL;
keyMap.erase(deleteNode->key);
delete deleteNode;
size--;
}
};
这是我第一次写的时候的代码:
class LRUCache{
public:
struct Node
{
int value;
int key;
Node * next;
Node * pre;
Node(int v, int k)
{
value = v;
key = k;
next = pre = 0;
}
};
LRUCache(int capacity) {
head = 0;
tail = 0;
hash = unordered_map<int, Node*>();
max_cap = capacity;
cur_cap = 0;
}
~LRUCache()
{
hash.clear();
Node* temp;
while (head)
{
temp = head;
head = head->next;
delete temp;
}
}
int get(int key) {
if (hash.find(key) != hash.end())
{
Node* cur = hash[key];
remove(cur);
push(cur);
return cur->value;
}
return -1;
}
void set(int key, int value) {
if (hash.find(key) != hash.end())
{
Node* cur = hash[key];
remove(cur);
push(cur);
cur->value = value;
}
else if (cur_cap < max_cap)//没有满
{
cur_cap++;
Node* newNode = new Node(value, key);
hash[key] = newNode;
push(newNode);
}
else
{
Node* newNode = new Node(value, key);
hash[key] = newNode;
push(newNode);
int key = popNode();
hash.erase(key);
}
}
private:
void remove(Node * n)//将节点从链表里取出,但是不释放空间
{
if (n == head)//n的前面没有节点
{
head = head->next;
if (head == 0)//唯一一个节点已经拿走
head = tail = 0;
else
head->pre = 0;
n->next = 0;
}
else if (n == tail)//至少2个节点,否则head == tail == n
{
tail = tail->pre;
tail->next = 0;
n->pre = 0;
}
else
{
n->pre->next = n->next;
n->next->pre = n->pre;
n->pre = n->next = 0;
}
}
void push(Node * n)//将节点放入尾部
{
if (head == 0)//0个节点
{
head = tail = n;
}
else//至少一个节点
{
tail->next = n;
n->pre = tail;
tail = n;
}
}
int popNode()//删除最开始的节点
{
if (head == 0)//0个节点
return 0;
else if (head == tail)//一个节点
{
int key = head->key;
delete head;
head = tail = 0;
return key;
}
else//至少2个节点
{
int key = head->key;
head = head->next;//head不可能为空
delete head->pre;
head->pre = 0;
return key;
}
}
Node * head;
Node * tail;
unordered_map<int, Node*> hash;
int max_cap;
int cur_cap;
};