leetcode之LRU实现

本文详细阐述了如何设计并实现一种基于Least Recently Used (LRU)原则的缓存数据结构,该结构支持get和set操作。通过结合使用map和双向链表,有效地实现了快速查找和排序功能,同时确保了在缓存达到容量时能够自动淘汰最近最少使用的项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值