LRU原理实现

本文详细介绍了LRU(Least Recently Used)缓存淘汰策略,以及如何使用C++实现基于HashMap和双向链表的LRU缓存。在内存有限的情况下,LRU策略用于决定何时从内存中移除不再使用的数据。文中代码展示了如何进行插入、删除和查找操作,以保持缓存的高效访问并遵循LRU原则。
摘要由CSDN通过智能技术生成

参考文章

leetcode链接

如何实现LRU(Least Recent Used)

为什么需要LRU?操作系统课程中,内存不够的场景下,淘汰旧内容的策略。

基于HashMap和双向链表实现LRU
使用HashMap存储key,这样可以做到put和get的时间都是O(1)。而HashMap的Value指向双向链表实现的LRU的Node节点。

1.put(key,value):首先在HashMap找到key对应的节点,如果节点存在,更新节点的值,并把这个节点移到表头。如果不存在,需要构造新的节点,并且尝试把节点塞到队头。如果LRU空间不足,则通过tail淘汰掉队尾的节点,同时在HashMap中移除Key。
2.get(key):通过查找HashMap找到LRU链表节点,因为根据LRU原理,这个节点是最新访问的,所以要把节点插入到队头,然后返回缓存的值。

文章代码链接
https://github.com/cpselvis/leetcode/blob/master/solution146.cpp

删除和插入双链表的知识:
双向链表的插入与删除(c++实现)
双向链表的插入及删除图解

https://github.com/cpselvis/leetcode/blob/master/solution146.cpp
c++代码

#include <iostream>
#include <map>

using namespace std;

struct CacheNode {
	int key;
	int value;
	CacheNode *pre, *next;
	CacheNode(int k,int v) : key(k),value(v), pre(NULL), next(NULL){}
};

class LRUCache {
private:
	int size;
	CacheNode *head, *tail;//使用伪头部和伪尾部节点
	map<int, CacheNode *> mp;


public:
	LRUCache(int capacity){
		size = capacity;
		head = NULL;
		tail = NULL;
	}

	int get(int key) {
		map<int, CacheNode *>::iterator it = mp.find(key);
		if (it != mp.end()) {
			//如果key存在,先通过哈希表定位,再移到头部
			CacheNode *node = it->second;
			remove(node);
			setHead(node);
			return node->value;
		}
		else {
			return -1;
		}
	}

	void set(int key, int value) {
		map<int, CacheNode *>::iterator it = mp.find(key);
		if (it != mp.end()) { //如果key存在,先通过哈希表定位,再修改value并移到头部
			CacheNode *node = it->second;
			node->value = value;
			remove(node);
			setHead(node);
		}
		else {//如果key不存在,创建一个新节点
			CacheNode *newNode = new CacheNode(key, value);
			if (mp.size() >= size) {
				map<int, CacheNode *>::iterator iter = mp.find(tail->key);
				remove(tail);
				mp.erase(iter);
			}
			setHead(newNode);
			mp[key] = newNode;
		}
	}

	//双链表的删除
	/*
	第一步:找到即将被删除的节点 p
	第二步:将 p 的前驱的后继指向 p 的后继,即 p->prior->next = p->next;
	第三步:将 p 的后继的前驱指向 p 的前驱,即 p->next->prior = p->prior;
	第四步:删除节点 p 即 delete p;
	*/
	void remove(CacheNode *node) {
		if (node->pre != NULL) {
			node->pre->next = node->next;
		}
		else {
			head = node->next;
		}
		if (node->next != NULL) {
			node->next->pre = node->pre;
		}
		else {
			tail = node->pre;
		}
	}
	/*
	当在链表头部插入节点,只需把新节点的右指针指向链表原来的第一个节点,再把原链表头左指针指向新节点即可,
用代码描述:
	insertnode->right= head;
	head->left = insertnode;
	head = insertnode;
	*/
	void setHead(CacheNode *node) {
		node->next = head;
		node->pre = NULL;
		if (head != NULL) {
			head->pre = node;
		}
		head = node;
		if (tail == NULL) {
			tail = head;
		}
	}

};


int main(int argc, char **argv) {
	LRUCache *lruCache = new LRUCache(2);
	lruCache->set(2, 2);
	lruCache->set(1, 1);
	cout << lruCache->get(2) << endl;
	lruCache->set(4, 4);
	cout << lruCache->get(1) << endl;
	cout << lruCache->get(4) << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值