手写一个LRU算法

LRU(Least Recently Used) 算法简介

最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最久的数据,这个算法可以保证内存(缓存)中的数据都是热点数据,从而保证了(内存页面)缓存命中率。

算法实现

思想:
根据LRU的算法思想,我们可以使用双向链表作为缓存来存储我们的数据,每当有访问某个数据时,便可以把这个节点从原来的位置删除,并插入到链表头部,这样能够保证链表尾部存储的是最近最久未使用的节点。当节点数超过缓存容量,那就删除尾部的节点。
问题:这样的话时间复杂度会很高,因为我们知道找到链表中某个节点只能有序遍历。这样的话时间复杂度是O(n),这事不能接受的,所以我们可以想办法,比如说使用HashMap来存储所有的节点。这样的话,查找的时候,只需要O(1)时间就可以得到目标节点。然后又因为我们使用的是双向链表,所以可以很方便的删除目标节点,并把左右两边连接起来。

代码:

测试类:

public class LRUTest {
    public static void main(String[] args) {
        LUR lur = new LUR<>(4);
        for (int i =0;i<10;i++){
            lur.put(i,i);
        }
    }
}

实现:


import java.util.HashMap;
import java.util.Iterator;

public class LUR implements Iterable {
    private Node head;
    private Node tail;
    private HashMap map;
    private int maxSize;

    private class Node {
        Node pre;
        Node next;
        K k;
        V v;

        public Node(K k, V v) {
            this.k = k;
            this.v = v;
        }
    }

    public LUR(int maxSize) {
        this.maxSize = maxSize;
        this.map = new HashMap<>(maxSize * 4 / 3);
        head = new Node(null, null);
        tail = new Node(null, null);
        head.next = tail;
        tail.pre = head;
    }

    public V get(K key) {
        if (!map.containsKey(key)) {
            return null;
        }
        Node node = map.get(key);
        unlink(node);
        appendHead(node);
        System.out.println("查询节点:" + node.k);
        return node.v;
    }

    public void put(K key, V value) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            unlink(node);
        }
        Node node = new Node(key, value);
        map.put(key, node);
        appendHead(node);
        System.out.println("添加节点:" + node.k);
        if (map.size() > maxSize) {
            Node toRemove = removeTail();
            System.out.println("移除节点:" + toRemove.k);
            map.remove(toRemove.k);
        }
    }

    private Node removeTail() {
        Node node = tail.pre;
        Node pre = node.pre;
        tail.pre = pre;
        pre.next = tail;
        node.next = null;
        node.pre = null;
        return node;
    }

    private void appendHead(Node node) {
        Node next = head.next;
        node.next = next;
        next.pre = node;
        node.pre = head;
        head.next = node;
    }

    private void unlink(Node node) {
        Node pre = node.pre;
        Node next = node.next;
        pre.next = next;
        next.pre = pre;

        node.pre = null;
        node.next = null;
    }


    @Override
    public Iterator iterator() {
        return new Iterator() {
            private Node curr = head.next;

            @Override
            public boolean hasNext() {
                return curr != tail;
            }

            @Override
            public K next() {
                Node node = curr;
                curr = curr.next; //仅仅知识遍历。不删除
                return node.k;
            }
        };
    }
}

你可能感兴趣的:(算法,java,操作系统)