分层双向链表+ 哈希表 实现LFU

为了实现LFU,对于每个页面,不仅需要记录访问时间的次序(用双向链表),还要记录访问频率(用HashMap,key是频率,value是这个频率下所有页面组成的双向链表),同时还有随机读写(用哈希表存储组织每个页面),所有一共有两个哈希表。
下图(来源leetcode题解https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/)解释了链表和哈希表组织方式:
在这里插入图片描述

class LFUCache {
    int capacity;
    int minfre;//当前最小的层数
    int cur;
    HashMap<Integer,doubleList> fre;//分层链表的map
    HashMap<Integer,Node> map1;//储存每一元素的map
    public LFUCache(int capacity) {
        this.capacity=capacity;
        fre = new HashMap<>();
        map1 = new HashMap<>();
        this.cur=0;

    }
    public int get(int key) {
        if(capacity==0) return-1;
        if(cur==0) return -1;
        if(map1.containsKey(key)){
            Node node=map1.get(key);//获取当前元素
            doubleList list = fre.get(node.fre);//获取元素所在的层
            if(list.size==1){//如果这一层只有一个元素 就删除整个层
                fre.remove(node.fre);
                if(minfre==node.fre) minfre++;//更新最小层minfre 此元素的层数必然会上升一层,所以minfre +1 必然
                //是新的最小层
                node.fre++;
                if(fre.containsKey(node.fre)){ // 把元素加入新的层
                    doubleList list1 = fre.get(node.fre);
                    list1.add(node);
                }
                else{
                    doubleList list2 =new doubleList();//如果当前层没有初始化就初始化
                    list2.add(node);
                    fre.put(node.fre,list2);
                }
            }
            else{
                node.fre++;
                list.remove(node);
               
                if(fre.containsKey(node.fre)){// 把元素加入新的层
                    doubleList list1 = fre.get(node.fre);
                    list1.add(node);
                }
                else{
                    doubleList list2 =new doubleList();
                    list2.add(node);
                    fre.put(node.fre,list2);
                }
            }

            return node.val;
        }
        else return -1;

    }
    
    public void put(int key, int value) {;
        if(capacity==0) return;
        if(map1.containsKey(key)){
           
            Node node=map1.get(key);
            node.val=value;
            get(key);
        }
        else{
            if(cur==capacity){ // 容量满了 就删除最小层的第一个元素
                doubleList list = fre.get(minfre);
                int thekey=list.first.next.key;
                if(list.size==1){
                    fre.remove(minfre);//删除整个层,因为这层空了
                    list=null;
                }
                else{
                    list.removeFirst();
                }
                map1.remove(thekey);
                cur--;
            }
            Node node = new Node(key,value);
            map1.put(key,node);
            if(fre.containsKey(1)){ // 新元素 插入第一层
                doubleList list = fre.get(1);
                list.add(node);
            
            }
            else{
                doubleList list = new doubleList();
                list.add(node);
                fre.put(1,list);
                
            }
        cur++;
        minfre=1;//更新最小层
        }
        
        
    }
}
class Node{

    int fre;
    int val;
    int key;
    Node pre;
    Node next;
    public Node(int key,int value){
        this.fre=1;
        this.val=value;
        this.key=key;
    }
    public Node(){
        val=11;
    }
}
class doubleList{//双向链表
    int size;
    Node first;
    Node last;
    public doubleList(){
        size=0;
        first=new Node();
        last=new Node();
        last.pre=first;
        first.next=last;

    }
    public void add(Node node){
        node.pre=last.pre;
        last.pre.next=node;
        node.next=last;
        last.pre=node;
        size++;
    }
    public void removeFirst(){
        first.next.next.pre=first;
        first.next=first.next.next;
        size--;
    }
    public void remove(Node node){
        node.pre.next=node.next;
        node.next.pre=node.pre;
        size--;
        node=null;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值