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
}

 

posted @ 2020-07-19 09:15  知道了呀~  阅读(587)  评论(0编辑  收藏  举报