LRU算法

什么是LRU

        LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常著名的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,存在一种缓存淘汰机制,每次从内存中找到最久未使用的数据然后置换出来,从而存入新的数据!它的主要衡量指标是使用的时间,附加指标是使用的次数。在计算机中大量使用了这个机制,它的合理性在于优先筛选热点数据,所谓热点数据,就是最近最多使用的数据!

怎么实现

这个题的设计思路就是哈希表加双向链表(需要定制,从尾部加,从头部出)
为什么需要哈希表呢?
       假设我们需要存储(A,3)这样一个数据,这里哈希表中存储的key为对应的A,而value则是这样一个节点的内存地址。这样,我们在修改的时候可以通过哈希表直接修改双向链表中的内容,并且当我们需要进行优先级的调整的时候可以以常数时间复杂度找到对应节点而不需要遍历行为。
框图如下
在这里插入图片描述

示例代码

#include <iostream>
#include <unordered_map>
using namespace std;

class Node
{
public:
	Node(int value)
		:m_value(value)
		, next(nullptr)
		, last(nullptr)
	{

	}
public:
	int m_value;
	Node *next;
	Node *last;
};

class NodeDoubleLinkedList
{
public:
	NodeDoubleLinkedList()
		:head(nullptr)
		, tail(nullptr)
	{

	}

	// 增加一个节点
	void addNode(Node &newNode)
	{
		if (head == nullptr)
		{
			head = &newNode;
			tail = &newNode;
		}
		else
		{
			tail->next = &newNode;
			newNode.last = tail;
			tail = tail->next;
		}
	}

	// 将节点移动到队列尾,也就是提升其优先级为最高
	void moveNodeToTail(Node &node)
	{
		if (&node == tail)
		{
			return;
		}
		if (&node == head)
		{
			head = head->next;
			head->last = nullptr;
		}
		else
		{
			node.last->next = node.next;
			node.next->last = node.last;
		}
		tail->next = &node;
		node.last = tail;
		node.next = nullptr;
		tail = tail->next;
	}
	// 删除队列头
	Node *removeHead()
	{
		if (head == nullptr)
		{
			//抛出异常
			//return nullptr;
		}
		Node *res = head;
		if (this->head == this->tail)
		{
			this->head = nullptr;
			this->tail = nullptr;
		}
		else
		{
			head = res->next;
			head->last = nullptr;
			res->next = nullptr;
		}
		return res;
	}
public:
	Node *head; // 优先级低
	Node *tail; // 优先级高
};

class MyCache
{
public:
	MyCache(int capacity)
	{
		if (capacity < 1)
		{
			throw exception("capacity error");
		}

		this->capacity = capacity;
	}
	// 由key查询对应的value
	int get(int key)
	{
		if (keyNodeMap.find(key) == keyNodeMap.end())
		{
			throw exception("key not exist");
		}
		Node *res = keyNodeMap[key];
		nodeList.moveNodeToTail(*res);
		return res->m_value;
	}
	// 加入键值对
	void set(int key, int value)
	{
		if (keyNodeMap.find(key) != keyNodeMap.end())
		{
			Node * node = keyNodeMap[key];
			node->m_value = value;
			this->nodeList.moveNodeToTail(*node);
		}
		else
		{
			Node *newNode = new Node(value);
			this->keyNodeMap[key] = newNode;
			this->nodeKeyMap[newNode] = key;
			this->nodeList.addNode(*newNode);
			if (this->keyNodeMap.size() == this->capacity + 1)
			{
				this->removeMostUnusedCache();
			}
		}
	}
	// 删除优先级最低的数据
	void removeMostUnusedCache()
	{
		Node *removeNode = this->nodeList.removeHead();
		int removeKey = this->nodeKeyMap[removeNode];
		this->nodeKeyMap.erase(removeNode);
		this->keyNodeMap.erase(removeKey);
	}
private:
	unordered_map<int, Node*> keyNodeMap;
	unordered_map<Node*, int> nodeKeyMap;	// 
	int capacity;							// 模拟内存大小
	NodeDoubleLinkedList nodeList;			// 优先级队列,越靠近tail,优先级越高

};

int main(int argc, char ** argv)
{
	MyCache testCache(3);
	testCache.set(1,2);
	testCache.set(2,3);
	testCache.set(3,4);

	testCache.get(1);

	system("pause");
	return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值