手写双向链表以实现LRU

算是LeetCode上面一道非常著名的题目了,原理就是手写一个双向链表,然后和HashMap组合在一起最终实现LRU算法


class LRUCache {
    HashMap<Integer, Node> map;
    DoubleLinkedList cache;
    int cap;

    public LRUCache(int capacity) {
// map中的key只是作为唯一标识符,用于快速地找到value,value则存储的是双向链表的节点
        map = new HashMap<>();
        cache = new DoubleLinkedList();
// 指定缓存的大小
        cap = capacity;
    }

    public int get(int key) {
        if (map.containsKey(key)) {
            // 通过key在O(1)内找到value,这个value是节点,val代表的是value这个节点的值,这点一直没搞清楚
            int val = map.get(key).value;
            put(key, val);
            // get方法最后必须返回它的值,其实就那道题的测试用例看起来,val和key是同一个
            return val;
        }
        return -1;
    }

    public void put(int key, int value) {
// 没有对Node进行传参的话,需要new这个对象
        Node newNode = new Node(key, value);
        if (map.containsKey(key)) {
            cache.delete(map.get(key));
            cache.addHead(newNode);
            map.put(key, newNode);
        } else {
            if (map.size() == cap) {
                //deleteLast
// 这里要注意的就是删除的是最后一个,map中remove也也是它的key,这也是为什么删除的返回值需要为int
                int k = cache.deleteLast();
                // map remove
                map.remove(k);
            }
            // addFirst
            cache.addHead(newNode);
            // add to map
            map.put(key, newNode);
        }
    }

    class DoubleLinkedList {
         Node head;
         Node tail;

        public DoubleLinkedList() {
            head = new Node(0, 0);
            tail = new Node(0, 0);

            head.next = tail;
            tail.prev = head;
        }

        public void addHead(Node node) {
            node.next = head.next;
            node.prev = head;
            // 这里要注意,如果先指定了head.next,那么head.next.prev就会空了
            head.next.prev = node;
            head.next = node;

        }

        public int delete(Node node) {
            int key = node.key;
            node.next.prev = node.prev;
            node.prev.next = node.next;
            return key;
        }

        public int deleteLast() {
            if(head.next==tail){
                return -1;
            }
            return delete(tail.prev);
        }
    }


    class Node {
        public int key;
        public int value;
        public Node prev;
        public Node next;

        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
posted @ 2021-08-17 16:16  concise_d  阅读(112)  评论(0)    收藏  举报