什么是LRU页面置换算法
LRU(Least Recently Used),是页面置换算法的一种,它的主要思想是当用于缓存页面的地址块已满时,选择最久未使用的页面删除,然后用将新请求的页面加入缓存。
例如:请求为 {1, 2, 0, 3, 0, 1, 2, 3, 2},缓存大小为3,那么
1 | 2 | 0 | 3 | 0 | 1 | 2 | 3 | 2 | |
地址块1 | 1 | 1 | 1 | 3 | 3 | 3 | 2 | 2 | 2 |
地址块2 | - | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 |
地址块2 | - | - | 0 | 0 | 0 | 0 | 0 | 3 | 3 |
实现代码
使用双向链表,每次删除时删除链表第一个页面,加入页面时放在链表末尾。
如果发现请求的页面已经在链表中了,那么直接把这个页面移动到链表末尾。
查找页面是否在链表中可以使用unordered_map实现。
//LRU
#include <iostream>
#include <vector>
#include <cstdio>
#include <unordered_map>
using namespace std;
#define MAX_LEN 4
struct Node {
int val;
Node *next, *last;
Node(int v) : val(v) {}
};
unordered_map<int, Node*> in_list;
Node* head;
Node* tail;
int list_len = 0;
void pushBack(Node *newNode) {
newNode->next = tail;
newNode->last = tail->last;
newNode->last->next = newNode;
tail->last = newNode;
in_list[newNode->val] = newNode;
list_len++;
printf("%d : in!\n", newNode->val);
}
void popFront() {
if (head->next == tail) return;
Node* first = head->next;
head->next = first->next;
first->next->last = head;
in_list[first->val] = nullptr;
list_len--;
printf("%d : out!\n", first->val);
delete first;
}
void print() {
Node* tmp = head->next;
while(tmp != tail) {
printf("%d ", tmp->val);
tmp = tmp->next;
}
printf("\n");
// tmp = tail->last;
// while(tmp != head) {
// printf("%d ", tmp->val);
// tmp = tmp->last;
// }
// printf("\n");
}
int main() {
// upcoming pages
vector<int> v = {1, 2, 0, 3, 0, 1, 2, 3, 2};
head = new Node(0);
tail = new Node(0);
head->next = tail, tail->last = head;
for (int id : v) {
if (in_list[id] != NULL && in_list[id] != nullptr) {
Node* p = in_list[id];
p->last->next = p->next;
p->next->last = p->last;
delete p;
list_len--;
}
if (list_len >= MAX_LEN) popFront();
Node* newNode = new Node(id);
pushBack(newNode);
print();
}
}