leetcode:LRU Cache
1 /* 2 Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. 3 4 get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. 5 set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, 6 it should invalidate the least recently used item before inserting a new item. 7 Problem link: https://oj.leetcode.com/problems/lru-cache/ 8 9 Author: Vincent Zhang 10 */ 11 12 #include <map> 13 using namespace std; 14 15 struct CacheNode { 16 int key; 17 int value; 18 CacheNode* prev; 19 CacheNode* next; 20 CacheNode(int k,int v) : key(k), value(v), prev(NULL), next(NULL) {} 21 }; 22 23 class LRUCache{ 24 public: 25 LRUCache(int capacity) { 26 this->cache_capacity = capacity; 27 head = NULL; 28 tail = NULL; 29 } 30 31 int get(int key) { 32 map<int,CacheNode*>::iterator it = cache_map.find(key); 33 if (it == cache_map.end()) 34 return -1; 35 else 36 { 37 CacheNode *tp = it->second; 38 moveToHead(tp); 39 return tp->value; 40 } 41 } 42 43 void set(int key, int value) { 44 map<int,CacheNode*>::iterator it = cache_map.find(key); 45 // new key and value 46 if (it == cache_map.end()) 47 { 48 // cache is full, release the LRU one and add new 49 if (cache_map.size() == cache_capacity) 50 { 51 cache_map.erase(tail->key); 52 tail->key = key; 53 tail->value = value; 54 CacheNode *tp = tail; 55 moveToHead(tp); 56 57 cache_map.insert(map<int,CacheNode*>::value_type(key,tp)); 58 } 59 else // cache is not full, add new 60 { 61 CacheNode *newNode = new CacheNode(key,value); 62 attachToHead(newNode); 63 cache_map.insert(map<int,CacheNode*>::value_type(key,newNode)); 64 } 65 66 } 67 else // has an exist node 68 { 69 CacheNode *tp = it->second; 70 tp->value = value; 71 72 isolateNode(tp); 73 attachToHead(tp); 74 } 75 76 } 77 private: 78 int cache_capacity; 79 CacheNode *head,*tail; 80 map<int,CacheNode*> cache_map; 81 82 void moveToHead(CacheNode *node) 83 { 84 if (node == head) 85 return; 86 else 87 { 88 isolateNode(node); 89 attachToHead(node); 90 } 91 } 92 void isolateNode(CacheNode* node) 93 { 94 if (node->prev != NULL) 95 node->prev->next = node->next; 96 else // node is head 97 head = node->next; 98 99 if (node->next !=NULL) 100 node->next->prev = node->prev; 101 else // node is tail 102 tail = node->prev; 103 104 node->next = NULL; 105 node->prev = NULL; 106 } 107 void attachToHead(CacheNode* node) 108 { 109 // head is null, list is empty 110 if (head == NULL) 111 { 112 head = node; 113 tail = head; 114 } 115 else 116 { 117 node->next = head; 118 head->prev = node; 119 head = node; 120 } 121 } 122 };