标签:
题目:
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
思路:
首先想到至少要维护两个数据结构,一个存key,value对本身(数据结构一),一个要记录访问记录排序,对第一个数据结构,由于需要快速查找,考虑用map存储,关于第二个数据结构,考虑两点,第一要顾及到排序,第二,要顾及到更新,因为有序是该数据结构的必然要求,而更新是该数据结构最常见的操作,基于这两点,考虑到用链表(数据结构二),但是链表有个问题,就是查找速度太慢,需要从头到尾扫描,这样的时间复杂度是肯定通不过leetcode OJ 的test case的,而在做更新的时候,是需要快速定位到某个节点的,所以要么把不用链表,换成其他数据结构,要么要再加一个数据结构以对链表进行记录,那么考虑用map吧(数据结构三)。有了这三个数据结构以后,考虑到数据结构二的更新操作涉及到节点移动,并需要记录最后一个节点(最近最少使用节点,这里把最近用过的节点都放在链表头部,最少使用的放在尾部,按最近访问顺序依次排序),设置一个类变量记录最后一个节点的地址,以减少搜索该节点的时间。
代码:
struct OrderNode { int key; OrderNode *next; OrderNode *prev; OrderNode(int x) : key(x), next(NULL), prev(NULL){}; }; class LRUCache{ private: std::map<int, OrderNode*> orderfinder; //find the previous node of the node in the order list OrderNode * orderlist; std::map<int, int> slot; int capacity; OrderNode * lastNode; public: LRUCache(int capacity) { this->capacity = capacity; orderlist = NULL; } int get(int key) { //not found if (slot.find(key) == slot.end()) { return -1; } else //found key { //record access for the node an update the access list; OrderNode* keyplace = orderfinder[key]; //if the first node if (keyplace->prev == NULL) { return slot[key]; } keyplace->prev->next = keyplace->next; //if not lastNode if (keyplace->next != NULL) { keyplace->next->prev = keyplace->prev; } else{ lastNode = lastNode->prev; lastNode->next = NULL; } keyplace->prev = NULL; keyplace->next = orderlist; orderlist->prev = keyplace; orderlist = keyplace; return slot[key]; } } void set(int key, int value) { //initialization of empty orderlist if (orderlist == NULL) { OrderNode *tmp = new OrderNode(key); orderlist = tmp; orderfinder.insert(std::pair<int, OrderNode*>(key, tmp)); slot.insert(std::pair<int, int>(key, value)); lastNode = tmp; } else if (slot.find(key) != slot.end()) //found the key already exist { //change the existing value slot[key] = value; //update the orderlist by moving the node to first OrderNode* keyplace = orderfinder[key]; if (keyplace == orderlist)//already the in first place { return; } if (keyplace->next != NULL)// IF NOT THE LAST ELEMENT { keyplace->next->prev = keyplace->prev; } else { lastNode = keyplace->prev; } keyplace->prev->next = keyplace->next; keyplace->prev = NULL; keyplace->next = orderlist; orderlist->prev = keyplace; orderlist = keyplace; } else if ((int)slot.size()<capacity) //still has space to insert { //insert new node slot.insert(std::pair<int, int>(key, value)); OrderNode* tmp = new OrderNode(key); tmp->next = orderlist; orderlist->prev = tmp; orderlist = tmp; orderfinder.insert(std::pair<int, OrderNode*>(key, tmp)); } else //push the last node out of orderlist { //insert new node slot.insert(std::pair<int, int>(key, value)); OrderNode* tmp = new OrderNode(key); if (capacity>1) { tmp->next = orderlist; orderlist->prev = tmp; //update slot using delete element from map slot.erase(slot.find(lastNode->key)); OrderNode* pre = lastNode->prev; orderfinder.erase(orderfinder.find(lastNode->key)); //update lastNode after pushing out lastNode = pre; lastNode->next = NULL; } else{ tmp->next = NULL; slot.erase(slot.find(lastNode->key)); orderfinder[lastNode->key] = tmp; OrderNode * p = orderlist; delete p; lastNode = tmp; } orderlist = tmp; orderfinder.insert(std::pair<int, OrderNode*>(key, tmp)); } } };
标签:
原文地址:http://blog.csdn.net/xunileida/article/details/42089247