LRU算法list链表实现
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
1存在
存在就比较简单了,直接取出数据,页面数据不变,并把这个结点放在list链表最前面,删除原来位置的节点
2不存在
cache满
把最靠后的页面删除,然后把需要的页面放到最前的位置
cache不满
直接去读取数据,然后把他放在最前的位置
#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; } C++ list 因为内部就是双向链表
go语言实现
type LRUCache struct { size int capacity int cache map[int]*List //hash链表,但是链表只有一个节点,用于判断某个key是否存在,以及快速定位某个key的位置 head, tail *List //双向链表节点 } type List struct { key, value int prev, next *List } func NewLRUCache(capacity int) LRUCache { c := LRUCache{ cache: map[int]*List{}, head: &List{}, tail: &List{}, capacity: capacity, } //初始化头尾节点都是空,这两个节点不包含在size里面 c.head.next = c.tail c.tail.prev = c.head return c } func (c *LRUCache) Get(key int) int { if _, ok := c.cache[key]; !ok { return -1 } node := c.cache[key] c.moveToHead(node)//读触发更新,读取的节点移动到头部 return node.value } func (c *LRUCache) Put(key int, value int) { if _, ok := c.cache[key]; !ok {//key不在缓存 node := &List{ key: key, value: value, } c.cache[key] = node c.addToHead(node) //key放列表头部 c.size++ if c.size > c.capacity { //判断是否需要淘汰尾部 lastNode := c.tail.prev //头尾指针不能算是缓存节点,实际上最后一个节点是尾指针的前一个节点 c.deleteNode(lastNode) //删除value delete(c.cache, lastNode.key) //删除map的映射关系 c.size-- } } else {//key已经存在,key从原来的位置移动到头部 node := c.cache[key] node.value = value c.moveToHead(node) } } func (c *LRUCache) addToHead(node *List) { //头指针的下一个节点才算是第一个节点 head->first->second->tail node.prev = c.head node.next = c.head.next c.head.next.prev = node c.head.next = node } func (c *LRUCache) deleteNode(node *List) { node.prev.next = node.next node.next.prev = node.prev } func (c *LRUCache) moveToHead(node *List) { c.deleteNode(node) c.addToHead(node) } func (c *LRUCache) removeTail() *List { node := c.tail.prev c.deleteNode(node) return node }
等风起的那一天,我已准备好一切