LRU是Least Recently Used的縮寫,即最近最少使用,是一種常用的頁面置換算法,選擇最近最久未使用的頁面予以淘汰。該算法賦予每個頁面一個訪問字段,用來記錄一個頁面自上次被訪問以來所經歷的時間 t,當須淘汰一個頁面時,選擇現有頁面中其 t 值最大的,即最近最少使用的頁面予以淘汰。
為什么要使用鏈表實現呢,因為這個頁面不會很多,內存和資源開銷都小
在計算機中,開銷往往是需要考慮的,我們不希望占用過多的系統資源,動態路由小型網絡使用RIP(Bellman-Ford Routing Algorithm),大型網絡設備用的就是OSPF(dijkstra),當然也有很多方面的考慮,比如RIP配置和管理更簡單,RIP為了避免出現網絡延遲太高,也將路由器最大的允許跳數設為15
我們存儲的時候就按照時間吧,末尾為剛剛使用的,淘汰前面的
然后我們來考慮下這個算法,保證我們不使用無關變量。這個cache是空的
進行一次請求需要查看我當前的cache里是否存在這個數據
1存在
存在就比較簡單了,直接取出數據,頁面數據不變,並把這個結點放在最后
2不存在
2.1cache滿
把最靠前的頁面用讀取數據的數據覆蓋,然后把它放到最后的cache
2.2cache不滿
直接去讀取數據,然后把他放在最后的頁面
我需要維護的是一個編號(或者說地址)還有后結點,然后查詢肯定是O(1)的,這是內部完成的,不需要我考慮(直接得到地址去取數據)
缺頁中斷都對應了一個硬件操作,就是去取這個數據
#include <stdio.h> #include <stdlib.h> struct node { int id; struct node *next; } * head, *tail, *p; void PushBack() { /* pre沒有意義,僅需要多保留一個尾結點 p->pre = tail; //使pre指向前一個節點,循環可得到反向鏈表 */ p->next = NULL; tail->next = p; tail = p; } void fun() { struct node *q; q = head; while (q->next != NULL) { if (q->next->id == p->id)//不缺頁 { PushBack(); p = q->next; q->next = p->next; free(p); return; //執行完全部操作停掉 } q = q->next; } printf("發生缺頁中斷 %d\n",p->id); PushBack(); p = head->next; head->next = p->next; free(p); } int main() { int sum, n, i; sum = 0; //初始cache內沒有數據 scanf("%d", &n); //讀入頁數 head = (struct node *)malloc(sizeof(struct node)); head->next = NULL; tail = head; while (1) { p = (struct node *)malloc(sizeof(struct node)); scanf("%d", &p->id); if (p->id < 0) { break; } else { if (sum < n) //cache未滿,放至后面 { PushBack(); printf("發生缺頁中斷 %d\n",p->id); sum += 1; //並對cache+1 } else { fun(); } } } return 0; }
事后來看,我說pre沒有意義是不對的,因為實際上並不是亂序的,往往我們先訪問的到的會被繼續訪問,並不是一個完全的均攤復雜度。
所以應該記錄pre進行倒序,有興趣的可以實現一下,不過我還是覺得c++好寫,但是內部肯定是更厲害的
c++實現就用list搞一下啊,把最近訪問的放到最前面

#include<iostream> #include<list> void fun(std::list<int>&L,int x) { for(std::list<int>::iterator it=L.begin();it!=L.end();it++) { if(*it==x) { L.push_front(x); L.erase(it); return; } } std::cout<<"發生缺頁中斷 "<<x<<std::endl; L.pop_back(); L.push_front(x); } int main() { std::list<int>L; int sum, n, i,x; sum = 0; //初始cache內沒有數據 std::cin>>n; //讀入頁數 while (true) { scanf("%d", &x); if (x < 0) { break; } else { if (sum < n) //cache未滿,放至后面 { L.push_front(x); std::cout<<"發生缺頁中斷 "<<x<<std::endl; sum += 1; //並對cache+1 } else { fun(L,x); } } } return 0; }

public class LRUCache{ private int limit; private HashMap<String,Node> hashMap; private Node head; private Node end; public LRUCache(int limit) { this.limit = limit; hashMap = new HashMap<String,Node>(); } public String get(String key){ Node node = hashMap.get(key); if(node ==null) return null; refreshNode(node); return node.value; } public void put(String key,String value){ Node node = hashMap.get(key); if(node == null){ if(hashMap.size()>=limit) { String oldKey = removeNode(head); hashMap.remove(oldKey); } node = new Node(key,value); addNode(node); hashMap.put(key,node) }else{ node.value = value; refreshNode(node); } } public void remove(String key){ Node node = hashMap.get(key); removeNode(node); hashMap.remove(key); } private void refreshNode(Node node) { if(node == end) return; removeNode(node); addNode(node); } public String removeNode(Node node){ if(node == end) end = end.pre; else if(node ==head) head = head.next; else { node.pre.next = node.next; node.next.pre = node.pre; } return node.key; } public void addNode(Node node) { if(end!=null) { end.next = node; node.pre = end; node.next = null; } end = node; if(head == null) head = node; } }