LRU缓存算法JAVA实现

LRU缓存是指在插入新数据时如果超过了该缓存的容量就将最久未使用的数据释放掉,这是leetcode146的题目,题目如下所示:

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

    首先LRU缓存要求要淘汰最久未使用的数据,所以我们存放的数据它有个先后的顺序,这里我想到的数据结构就是链表,又因为需要判断关键字key是否存在于缓存中,如果只是单纯的链表数据结构的话遍历出这个key的时间复杂度是o(n),所以我们考虑给他升个级再给它加一个哈希表,哈希表key存关键字,value存相应的链表节点,这样就能很快的判断缓存中是否有该关键字对应的数据。(最后贴上我年老失修的代码,如果有更简洁的写法可以贴给我^^)

class LRUCache {

  class Node {
    public int key,val;
    public Node next, prev;
    public Node( int v,int k) {
        this.val = v;
        this.key=k;
    }
}
    //缓存的容量
    private int capacity;
    private Map<Integer,Node> map=new HashMap<Integer, Node>();
    //头节点
    private Node head;
    //当前已存储的量
    private int now=0;
    public LRUCache(int capacity) {
    this.capacity=capacity;
    }
    
    //获取数据
    public int get(int key) {
     //先看map中是否含有 没有return -1
     //有的话 先将该节点移除 再加入到头节点
     if(map.containsKey(key)){
         Node node = map.get(key);
         remove(node);
         putH(node);
         return node.val;
     }
     else {
         return -1;
     }
    }
    //插入数据
    public void put(int key, int value) {
     //先看缓存是否含有  1.有则将该节点的值修改,并插入头节点   2.没有则加入到头节点 并判断是否要弹出尾节点
        if(map.containsKey(key)){
            Node node=map.get(key);
            node.val=value;
            //如果已经是头节点就不用操作了
            if(head!=node){
                remove(node);
                putH(node);
            }

        }
        else {
            Node node=new Node(value,key);
            if(head==null){
                head=node;
                head.next=head;
                head.prev=head;
                now++;
                map.put(key,node);
                return;
            }
            putH(node);
            map.put(key,node);
            now++;
            if(now>capacity){
                map.remove(head.prev.key);
                remove(head.prev);
            }
        }

    }
   //将节点插入到头部
    public void putH(Node node){
        node.next=head;
        node.prev=head.prev;
        head.prev.next=node;
        head.prev=node;
        head=node;

    }
   //移除当前节点
    private void remove(Node node){
        node.prev.next=node.next;
        node.next.prev=node.prev;

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值