C++ 手写LRU缓存机制(力扣146. LRU 缓存)

1.概念:

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

2.题目要求:原题

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

3.代码分为两部分:

  1. get / put:用于数据的获取和更新
  2. move_to_head / add_to_head / remove / delete_tail:用于链表相关的操作

4.注意点:

  • 1.类成员要有size / capacity,head / tail
  • 2.unordered_map 只能存储key 和 node
  • 3.在删除链表尾部时,记得在unordered_map也要erase掉

5.代码:

#include
#include
#include
using namespace std;

struct ListNode {
	ListNode* pre;
	ListNode* next;
	int val;
	int key;
	ListNode(int _key, int _val):key(_key),val(_val),pre(nullptr),next(nullptr) {};
};

class LRU {
private:
	const static int default_capacity = 50;
	ListNode* head, * tail;
	unordered_mapmp;
	int size;
	int capacity;
public:
	LRU():size(0), capacity(default_capacity) {
		head = new ListNode(0, 0);
		tail = new ListNode(0, 0);
		head->next = tail;
		tail->pre = head;
	}

	LRU(int _capacity) :size(0), capacity(_capacity) {
		head = new ListNode(0, 0);
		tail = new ListNode(0, 0);
		head->next = tail;
		tail->pre = head;
	}

	~LRU() {
		while (head) {
			ListNode* tmp = head;
			head = head->next;
			delete tmp;
		}
	}

	void put(int key, int value) { // 插入或者更新
		if (mp.find(key) != mp.end()) {
			ListNode* node = mp[key];
			node->val = value;
			move_to_head(node);
		}
		else {
			ListNode* newNode = new ListNode(key, value);
			mp[key] = newNode;
			add_to_head(newNode);
			++size; // 记得更新
			if (size > capacity) {
				ListNode* node = delete_tail();
				mp.erase(node->key); // 记得erase
				delete node;
				--size; // 记得更新
			}
		}
	}

	int get(int key) { // 获取数据
		if (mp.find(key) != mp.end()) {
			ListNode* node = mp[key];
			move_to_head(node);
			return node->val;
		}
		return -1;
	}

	void print() { // 为了测试,打印整个链表(不打印头尾节点)
		ListNode* cur = head->next;
		while (cur != tail) {
			cout << cur->val;
			cur = cur->next;
		}
		cout << endl;
	}
private:
	void add_to_head(ListNode* node) { // 向链表头部添加node
		head->next->pre = node;
		node->next = head->next;
		node->pre = head;
		head->next = node;
	}

	void move_to_head(ListNode* node) { // 将node移到链表头部
		remove(node);
		add_to_head(node);
	}

	void remove(ListNode* node) { // 移除node(注意:是从链表中移除,并没有删除节点)
		node->pre->next = node->next;
		node->next->pre = node->pre;
	}

	ListNode* delete_tail() { // 移除尾部节点(最近最少使用节点),并返回该节点便于erase和delete操作
		ListNode* tmp = tail->pre;
		remove(tmp);
		return tmp;
	}
};

int main() {
	LRU lru(2);
	lru.put(1, 1);
	lru.print();
	lru.put(4, 2);
	lru.print();
	cout << lru.get(4) << endl;
	lru.put(4, 3);
	lru.print();
	return 0;
}

仅做笔记使用,如有不足还望指点!!溜了溜了~

你可能感兴趣的:(C++,C++,缓存,链表,数据结构)