首页 > 代码库 > leetcode之LRU实现

leetcode之LRU实现

题目:

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));
		}
	}
};


leetcode之LRU实现