An implementation with hash table and a double linked list
//get(int key): O(1) through hash table to List Node, then return value
//when get a value existed int hash table, adjust List to make the node in the top of list O(1) time
//set(int key, int value): check whether key is in hash table, if so, adjust its value, and shiftup
//if it is not in hash table, size of List is smaller than capacity, then insert it in List and hash table
//If size of list is equal to capacity, delete one node in the end, then add new node in the beginning.
class LRUCache{
public:
struct ListNode{
int key;
int value;
ListNode *front;
ListNode *next;
ListNode(int k, int val)
:key(k), value(val), front(nullptr), next(nullptr)
{}
};
int capacity;
//<key, pointer in List>
unordered_map<int, ListNode*> hmap;
ListNode *head;
LRUCache(int capacity) {
this->capacity = capacity;
//maintain a double linked list
head = new ListNode(0,0);
head->front = head;
head->next = head;
}
bool empty()
{
return hmap.size()==0;
}
bool full()
{
return hmap.size()==capacity;
}
//when get or set an existing node, shift this node up to the head of list
void shiftup(ListNode *node)
{
//delete it from middle
node->front->next = node->next;
node->next->front = node->front;
//shift up to the head
node->next = head->next;
node->front = head;
head->next->front = node;
head->next = node;
}
//delete the node in the end of list
//also delete it from hash table
void pop()
{
int delkey = head->front->key;
ListNode *delNode = head->front;
head->front->front->next = head;
head->front = head->front->front;
hmap.erase(delkey);
delete delNode;
}
//push a new node to the end of list
void push(ListNode *node)
{
node->next = head->next;
node->front = head;
head->next->front = node;
head->next = node;
hmap.insert(make_pair(node->key, node));
}
int get(int key) {
//not exist
int value = -1;
if(hmap.find(key) != hmap.end()){
value = hmap[key]->value;
//if the node is not in head, shift it to head
if(head->next != hmap[key]){
shiftup(hmap[key]);
}
}
return value;
}
void set(int key, int value) {
//this key alreay exists
if(hmap.find(key) != hmap.end()){
//adjust its value and position
ListNode *node = hmap[key];
node->value = value;
shiftup(node);
return;
}
//if full, pop one node out
if(full()){
pop();
}
//push new node to the list
ListNode *node = new ListNode(key, value);
push(node);
}
};