1. 定义:
LRU算法,也就是最近最少使用算法,是一种用于操作系统缺页置换的算法,大概的思想是:操作系统维护一个页面单链表,新进入的页面和链表中被访问的页面移到链表头,链表满需要置换时从链表尾移除页面。
2. 程序代码:
实现LRU算法,维护一张链表,将新来的节点、访问到的节点都插入到链表的头部,如果链表长度超过容量,则移除尾部的节点。代码如下:
#include <iostream> using namespace std; class LRUCache { public: LRUCache(int capacity) { LRUlist_Len = capacity; cnt = 0; head = NULL; } /*查找key,若存在返回key对应的value,否则返回-1*/ int get(int key) { ListNode *cur = head; ListNode *precur = NULL; while(cur) { if(cur->kv.first == key) //找到之后,将找到的页放到链表头 { cout<<cur->kv.first<<" -> "<<cur->kv.second<<endl; if(precur != NULL) { precur->next = cur->next; cur->next = head; head = cur; return cur->kv.second; } else { return cur->kv.second; } } precur = cur; cur = cur->next; } cout<<"the key "<<key<<" is not in the LRU list"<<endl; return -1; } /*插入(key,value)节点,若已存在key则把该节点移到链表头,否则插入该节点到链表头*/ void set(int key, int value) { if(head == NULL) { head = new ListNode(key,value); cnt++; } else { ListNode *tmp = head; ListNode *pretmp = NULL; bool key_flag = false; while(tmp) { //在链表中找到key,则修改key对应的value值,并将该页移动到链表头 if(tmp->kv.first == key) { tmp->kv.second = value; if(pretmp != NULL) { pretmp->next = tmp->next; tmp->next = head; head = tmp; } key_flag = true; break; } pretmp = tmp; tmp = tmp->next; } if(!key_flag) //key还没有在缓存链表中,需要添加 { if(cnt < LRUlist_Len) //缓存未达到上限,将插入的新页放到链表头 { ListNode *newhead = new ListNode(key,value); newhead->next = head; head = newhead; cnt++; } else //缓存已到上限,移除链表尾的页,将新页放到链表头 { ListNode *cur = head; ListNode *precur = NULL; while(cur->next) { precur = cur; cur = cur->next; } if(precur != NULL) //precur不等于NULL,表明链表有多个节点 { ListNode *newhead = new ListNode(key,value); newhead->next = head; head = newhead; precur->next = NULL; delete cur; cur = NULL; } else //precur等于NULL,表明链表只有一个节点 { ListNode *newhead = new ListNode(key,value); newhead->next = NULL; delete head; head = newhead; } } } } } private: int LRUlist_Len; int cnt; struct ListNode { pair<int,int> kv; ListNode *next; ListNode(int key, int value) { kv.first = key; kv.second = value; next = NULL; } }; ListNode *head; }; int main() { LRUCache lc(5); lc.set(3,5); lc.set(6,188); lc.set(1,10); lc.set(8,1); lc.set(2,9); lc.set(1,5); lc.get(2); lc.set(4,17); lc.get(3); lc.get(1); return 0; }
运行结果如下: