算法---最近最少使用算法

LRU是Least Recently Used 近期最少使用算法

1. 原理

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。涉及到操作系统原理的部分知识
使用两种数据结构实现LRU Cache

  1. Queue: 是由双向链表实现的,队列的容量等于缓存的大小,最近使用的页在前端,最少使用的页在后端。队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
  2. Hash:page number as key and address of the corresponding queue node as value.
    引用页面(page)时,所需页面可能位于内存中。 如果它在内存中,我们需要分离列表的节点并将其带到队列的前面。
    如果所需页面不在内存中,我们将其带入内存。 简单来说,我们在队列的前面添加一个新节点,并更新哈希中相应的节点地址。 如果队列已满,即所有页框(page frame)都已满,我们从队列后面删除一个节点,并将新节点添加到队列的前面。
    例子如下:
    有一个字符串:
1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5

有3个页槽(page frame),找到页面错误(page faults)的数量。
在这里插入图片描述
在这里插入图片描述
注意:一开始内存为空。
算法如下:

**
 * @Author: HASEE
 * @Description: LRU算法
 * @Date: Created in 17:17 2019/3/5
 * @Modified By:
 */
public class LRUCache {

    /**
     * We can use Java inbuilt Deque as a double ended queue to store the cache keys,
     * with the descending time of reference from front to back and a set container
     * to check presence of a key. But remove a key from the Deque using remove(),
     * it takes O(N) time. This can be optimized by storing a reference (iterator)
     * to each key in a hash map.
     */
    // store key of cache
    static Deque<Integer> deque;
    // store references of key in cache
    static HashSet<Integer> map;
    // maximum capacity of cache
    static int csize;

    LRUCache(int n) {
        deque = new LinkedList<>();
        map = new HashSet<>();
        csize = n;
    }

    // Refers key x with in the LRU cache
    public void refer(int x) {
        if (!map.contains(x)) {
            if (deque.size() == csize) {
                int last = deque.removeLast();
                map.remove(last);
            }
        } else {
                /* The found page may not be always the last element, even if it's an
               intermediate element that needs to be removed and added to the start
               of the Queue */
            int index = 0, i = 0;
            Iterator<Integer> itr = deque.iterator();
            while (itr.hasNext()) {
                if (itr.next() == x) {
                    index = i;
                    break;
                }
                i++;
            }
            deque.remove(index);
        }
        deque.push(x);
        map.add(x);
    }

    // display contents of cache
    public void display() {
        Iterator<Integer> itr = deque.iterator();
        while(itr.hasNext()){
            System.out.print(itr.next() + " ");
        }
    }
    public static void main(String[] args) {
        LRUCache ca=new LRUCache(4);
        ca.refer(1);
        ca.refer(2);
        ca.refer(3);
        ca.refer(1);
        ca.refer(4);
        ca.refer(5);
        ca.display();
    }
}

结果:

5 4 1 3 

以上只是简单的描述LRU的原理。
常见的改进算法有:LRU-K、Two queues(2Q)、Multi Queue(MQ)等。
有关他们的具体比较。请参考:https://www.cnblogs.com/work115/p/5585341.html
https://www.cnblogs.com/work115/p/5585341.html
转载:
https://www.geeksforgeeks.org/lru-cache-implementation/

猜你喜欢

转载自blog.csdn.net/m0_37941483/article/details/88191892