手写LRU算法利用哈希链表LinkedHashMap

手写LRU算法利用哈希链表LinkedHashMap

简单的说一点需要注意的点:

  1. LRU算法高效的一点就是,修改数据和访问数据的时间复杂度为O(1),首先借助链表的有序性使得链表元素维持插入顺序,同时借助Hash映射的快速访问能力使得我们可以以O(1)的时间复杂度访问链表的任意元素,这一一种全新的数据结构,叫做哈希链表,
  2. 使用的链表,必须为双向链表,因为 我们需要删除操作,删除一个节点不仅要得到该节点本身的指针,也需要操作前驱的节点,而只有双向链表才能够直接查找前驱,保证时间复杂度为O(1)
//声明节点类
public class Node {
    public int key,val;
    public Node next,pre;

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


//存储的hash链表
public class DoubleList {
    private Node head,tail;
    private int size;

    public DoubleList(Node head, Node tail) {
        head = new Node(0,0);
        tail = new Node(0,0);
    }
    //在链表的尾部添加节点x 时间复杂度为O(1)
    public void addLast(Node x){
        tail.pre.next = x;
        tail.pre = x;
        x.pre = tail.pre;
        x.next = tail;
        size++;
    }
    //删除链表中节点,节点一定存在
    //由于是双向链表且给的目标是Node节点,时间复杂度啊为O(1)
    public void remove(Node x){
        x.pre.next = x.pre;
        x.next.pre = x.pre;
        size--;        
    }

    //删除链表中的节点,并且返回该节点,时间复杂度为O(1)
    public Node removeFirst() {
        if (head.next == tail) {
            return null;
        }
        Node first = head.next;
       remove(first);
       return first;
    }
    //返回链表的长度,时间为O(1)
    public int size(){
        return size;
    }
    
}

//利用linkedHashMap来实现LRU这一种缓存机制

public class LRUCache {
    int cap;
    LinkedHashMap<Integer,Integer> cache = new LinkedHashMap<Integer,Integer>();

    public LRUCache(int capacity) {
        this.cap = capacity;
    }
    /**
     * 思路:LRU缓存算法一共有三个核心的功能,第一个get :获取到当前的value 并且使他放在链表的最后端
     * 第二个put 有的话,删除该值,没有就添加,放在最后
     * makeRecently 这就是需要把当前节点重新最一个调整
     */
    
    public int get(int key){
        if (!cache.containsKey(key)) {
            return -1;
        }
        makeRecently(key);
        return cache.get(key);
    }

    public void put(int key, int value) {
        if (cache.containsKey(key)) {
            cache.put(key,value);
            makeRecently(key);
            return;
        }
        //如果超过的范围
        if (cache.size() >= cap) {
            int oldNode = cache.keySet().iterator().next();
            cache.remove(oldNode);
        }
        cache.put(key,value);
        return;
    }

    private void makeRecently(int key) {
        //将该值提成我们需要的首部信息
        int oldval = cache.get(key);
        cache.remove(key);
        cache.put(key,oldval);
    }
}

你可能感兴趣的:(leetcode,数据结构,链表,算法)