操作系统之LRU算法 C语言链表实现
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(int n,int *sum,int *page_faults_number) { 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); *page_faults_number +=1; PushBack(); if (*sum < n) //cache未满,放至后面 { *sum += 1; //并对cache+1 return; } //cache满,释放下最后一个节点 p = head->next; head->next = p->next; free(p); } int main() { int sum, n, i, page_faults_number; sum = 0; //初始cache内没有数据 page_faults_number = 0; //缺页次数清空 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 { fun(n,&sum,&page_faults_number); } } printf("发生缺页中断%d次\n",page_faults_number); return 0; }
事后来看,我说pre没有意义是不对的,因为实际上并不是乱序的,往往我们先访问的到的会被继续访问,并不是一个完全的均摊复杂度。
所以应该记录pre进行倒序,有兴趣的可以实现一下,不过我还是觉得c++好写,但是内部肯定是更厉害的。
内部实现是双向链表,因为可以自我删除,虽然浪费了空间,但是节约了时间
c++实现就用list搞一下啊,把最近访问的放到最前面
#include <iostream> #include <list> void fun(std::list<int> &L, int x, int n, int &sum, int &page_faults_number) { 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; page_faults_number += 1; L.push_front(x); if (sum < n) //cache未满 { sum += 1; //并对cache+1 return; } L.pop_back(); } int main() { std::list<int> L; int sum, n, i, x, page_faults_number; sum = 0; //初始cache内没有数据 page_faults_number = 0; std::cin >> n; //读入页数 while (true) { scanf("%d", &x); if (x < 0) { break; } else { fun(L, x, n, sum, page_faults_number); } } std::cout << "发生缺页中断 " << page_faults_number << "次" << std::endl; return 0; }
再加上map效率就更高了
#include <iostream> #include <list> #include <map> void fun(std::list<int> &L,std::map<int, std::list<int>::iterator> &M, int x, int n, int &sum, int &page_faults_number) { if (M.count(x)) { L.erase(M[x]); L.push_front(x); M[x] = L.begin(); return; } std::cout << "发生缺页中断 " << x << std::endl; page_faults_number += 1; L.push_front(x); M[x] = L.begin(); // std::cout << "发生缺页中断 " << x << std::endl; if (sum < n) //cache未满,放至后面 { sum += 1; //并对cache+1 return; } //把最后一个删除 M.erase(*L.rbegin()); L.pop_back(); } int main() { std::list<int> L; std::map<int, std::list<int>::iterator> M; int sum, n, i, x, page_faults_number; sum = 0; //初始cache内没有数据 page_faults_number = 0; std::cin >> n; //读入页数 while (true) { scanf("%d", &x); if (x < 0) { break; } else { fun(L,M, x, n, sum, page_faults_number); } } std::cout << "发生缺页中断 " << page_faults_number << "次" << std::endl; 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; } }
本文来自博客园,作者:暴力都不会的蒟蒻,转载请注明原文链接:https://www.cnblogs.com/BobHuang/p/11224447.html