LRU 算法 C++实现

实现LRU


LRU(Least Recently Used),即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰,常用于缓存机制。


实现LRU需要一个Map和一个双向链表。

我们规定,head->next 为最久未使用节点,head->prev为最新节点,每次当访问或修改已有节点时,将其移动到尾部,这样就可以保证其相对次序。

map的value保存链表节点的指针,保证O(1) 时间定位节点。

在这里插入图片描述

当缓存未满时,直接向map插入新项,链表尾插新节点。
当缓存已满,删除头结点,尾插新节点。

get时,需要刷新其相对次序,将其旧位置断链,重新尾插。

时间复杂度均为O(1)。



struct my_ListNode
{
	int _key;
	int _data;
	my_ListNode* _prev;
	my_ListNode* _next;

	my_ListNode(int key, int val) :
		_key(key),
		_data(val),
		_prev(nullptr),
		_next(nullptr) {}

};

class my_list
{
	typedef my_ListNode Node;
public:

	my_list() :
		_head(new Node(int(), int()))
	{
		_head->_prev = _head;
		_head->_next = _head;
	}

	~my_list() 
	{
		if (!empty())
		{
			Node* cur = _head->_next;
			while (cur != _head)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}

		}

		delete _head; 
	}

	bool empty()
	{
		return _head->_prev == _head && _head->_next == _head;
	}
	size_t size()
	{
		if (empty())
			return 0;
		size_t count = 0;
		Node* cur = _head->_next;
		while (cur != _head)
		{
			cur = cur->_next;
			count++;
		}

		return count;
	}

	//尾插
	void push_back(Node* newNode)
	{
		Node* tail = _head->_prev;

		newNode->_prev = tail;
		tail->_next = newNode;
		newNode->_next = _head;
		_head->_prev = newNode;
	}


	//返回key
	int pop_back()
	{
		if (empty())
			return -1;

		Node* tail = _head->_prev;
		int key = tail->_key;
		Node* newTail = tail->_prev;
		newTail->_next = _head;
		_head->_prev = newTail;

		//delete tail;

		return key;
	}


	//返回key
	int pop_front()
	{
		if (empty())
			return -1;

		Node* del = _head->_next;
		int key = del->_key;
		
		Node* next = del->_next;
		_head->_next = next;
		next->_prev = _head;

		delete del;

		return key;
	}


	void erase(Node* pos)
	{
		if (empty())
			return;

		Node* prev = pos->_prev;
		Node* rear = pos->_next;

		prev->_next = rear;
		rear->_prev = prev;

	}

private:
	Node* _head;
};



class LRUCache {
	typedef my_ListNode Node;
public:
	LRUCache(int capacity) :
		_capacity(capacity) {}

	int get(int key) {

		//找不到返回-1
		if (_mp.find(key) == _mp.end())
			return -1;

		Node* addr = _mp[key];
		int ret = addr->_data;

		//更新次序
		_li.erase(addr);
		_li.push_back(addr);

		return ret;
	}

	void put(int key, int value) {

		if (_mp.size() == _capacity && _mp.find(key) == _mp.end())
		{
			//先删除最近最少使用
			int del = _li.pop_front();
			_mp.erase(del);
		}

		if (_mp.find(key) != _mp.end())
		{
			Node* node = _mp[key];
			node->_data = value;

			_li.erase(node);
			_li.push_back(node);
		}
		else
		{
			Node* newNode = new Node(key, value);

			_mp.insert(pair<int, Node*>(key, newNode));
			_li.push_back(newNode);
		}

	}


private:

	const int _capacity;
	map<int, Node*> _mp;
	my_list _li;
};


int main()
{
	LRUCache* cache = new LRUCache(2);

	cache->put(2, 1);
	cache->put(2, 2);
	cout << cache->get(2) << endl;       // 返回  1
	cache->put(1, 1);
	cache->put(4, 1);
	cout << cache->get(2) << endl; ;       // 返回 -1 (未找到)

}

猜你喜欢

转载自blog.csdn.net/juggte/article/details/121314800
今日推荐