LRU算法


public class Solution {

    /**
     * lru的核心思想是最新使用或者最近创建的放置在链表的头部,越靠后说明距离上次使用越长,删除后面的元素即可,
     * 因为涉及到删除元素所以使用双向链表更加适合
     */

    // lru支持的总容量
    int capacity;
    // 已经使用的容量
    int size;
    // 缓存
    Map<Integer, ListNode> cache;
    // 头结点
    ListNode head;
    // 尾结点
    ListNode tail;

    public Solution(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        cache = new HashMap();
        head = new ListNode();
        tail = new ListNode();
        head.next = tail;
        tail.pre = head;
    }

    // 从缓存中获取
    public int get(int key) {
        ListNode node = cache.get(key);
        if (node != null) {
            // remove node to head
            removeToHead(node);
            return node.value;
        }
        return -1;
    }

    public void set(int key, int value) {
        ListNode node = cache.get(key);
        if (node == null) {
            // 缓存中不存在,存储即可
            ListNode newNode = new ListNode(key, value);
            addToHead(newNode);
            cache.put(key, newNode);
            size++;
            if (size > capacity) {
                // remove last node ;
                ListNode dNode = removeLastNode();
                cache.remove(dNode.key);
                size--;
            }
        } else {
            // key 已经存在,值有可能相同也可能不相同,直接覆盖即可
            node.value = value;
            // 修改缓存的值
            cache.put(key, node);
            // remove this node to head
            removeToHead(node);
        }

    }

    // 移除最后一个元素
    public ListNode removeLastNode() {
        // head >> 1 >> 2 >> 3 >> tail
        ListNode delNode = tail.pre;
        removeNode(delNode);
        return delNode;
    }

    // 移动节点到头节点
    public void removeToHead(ListNode node) {
        // 删除当前节点元素
        removeNode(node);
        // 在头结点处新增元素
        addToHead(node);
    }

    // 移除指定元素
    public void removeNode(ListNode node) {
        // head >> 1 >> 2 >> 3 >> tail
        // 假设需要移除元素2,则先需要获取2的前置元素1 让1指向删除元素的下一个元素。即 pre.next = node.next ;
        ListNode pre = node.pre;
        pre.next = node.next;
        node.next.pre = pre;
    }

    // 头节点添加元素
    public void addToHead(ListNode node) {
        // head >> 2 >> 3 >> tail
        // 假设需要向头节点添加元素1,因为目前的head是我们虚拟的一个头结点,所以只需要获取head.next指向新增的节点即可;
        ListNode temp = head.next;
        head.next = node;
        node.pre = head;
        node.next = temp;
        temp.pre = node;
    }


    class ListNode {
        int key;
        int value;
        ListNode next;
        ListNode pre;

        ListNode() {
        }

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

}

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值