LRU和LFU

25 篇文章 0 订阅
19 篇文章 0 订阅

LRU

在这里插入图片描述
双向链表+哈希表

class Node {
    String key;
    int value;
    Node pre;
    Node next;

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

class biLinkedList{
    Node head;
    Node tail;

    public biLinkedList() {
        this.head = null;
        this.tail = null;
    }

    public void addNode(Node newNode) {
        if (newNode == null) {
            return;
        }
        if (this.head == null) {
            this.head = newNode;
        }else {
            this.tail.next = newNode;
            newNode.pre = this.tail;
            newNode.next = null;
        }
        this.tail = newNode;
    }

    public void moveToTail(Node node) {
        if (this.tail == node) {
            return;
        }
        if (node == this.head) {
            this.head = node.next;
            this.head.pre = null;
        }else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        this.tail.next = node;
        node.pre = this.tail;
        node.next = null;
        this.tail = node;
    }

    public Node removeHead() {
        if (this.head == null) {
            return null;
        }
        Node res = this.head;
        if (this.head == this.tail) {
            this.head = null;
            this.tail = null;
        }else {
            this.head = res.next;
            this.head.pre = null;
            res.next = null;
        }
        return res;
    }
}

public class LRU {
    biLinkedList nodeList;
    HashMap<String, Node> keyNodeMap;
    int capacity;

    public LRU(int capacity) {
        if (capacity < 1) {
            throw new RuntimeException("capacity too small");
        }
        this.capacity = capacity;
        keyNodeMap = new HashMap<>();
        nodeList = new biLinkedList();
    }

    public int get(String key) {
        if (keyNodeMap.containsKey(key)) {
            Node res = keyNodeMap.get(key);
            this.nodeList.moveToTail(res);
            return res.value;
        }
        return -999;
    }

    public void set(String key, int value) {
        if (keyNodeMap.containsKey(key)) {
            Node res = keyNodeMap.get(key);
            res.value = value;
            nodeList.moveToTail(res);
        }else {
            Node newNode = new Node(key, value);
            keyNodeMap.put(key, newNode);
            nodeList.addNode(newNode);
            if (capacity + 1 == keyNodeMap.size()) {
                removeMostUnusedCache();
            }
        }
    }

    public void removeMostUnusedCache() {
        Node removeNode = nodeList.removeHead();
        keyNodeMap.remove(removeNode.key);
    }

    public static void main(String[] args) {
        LRU test =  new LRU(3);
        test.set("A", 1);
        test.set("B", 2);
        test.set("C", 3);
        System.out.println(test.get("B"));
        System.out.println(test.get("A"));
        test.set("D", 4);
        System.out.println(test.get("D"));
        System.out.println(test.get("C"));
    }
}

结果:
2
1
4
-999

LFU

package lfu;

import java.util.HashMap;

public class LFU {
    public static class Node{
        int key;
        int value;
        int times;
        Node up;
        Node down;

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

public static class LFUCache{

    public static class NodeList{
        Node head;
        Node tail;
        NodeList pre;
        NodeList next;

        public NodeList(Node node) {
            this.head = node;
            this.tail = node;
        }

        public void addNodeToHead(Node newNode){  // 新来的节点从头部添加,因而尾部是最早添加
            newNode.down = head;
            head.up = newNode;
            head = newNode;
        }

        public boolean isEmpty() {
            return head == null;
        }

        public void deleteNode(Node node) {
            if (head == tail) {
                head = null;
                tail = null;
            }else {
                if (node == head) {
                    head = head.down;
                    head.up = null;
                }else if (node == tail) {
                    tail = tail.up;
                    tail.down = null;
                }else {
                    node.down.up = node.up;
                    node.up.down = node.down;
                }
            }
            node.up = null;
            node.down = null;
        }
    }

    int capacity;
    int size;
    NodeList headList;
    HashMap<Integer, Node> records;  // key对应的Node
    HashMap<Node, NodeList> heads;  // Node 在哪个NodeList中

    public LFUCache(int capacity,  NodeList headList, HashMap<Integer, Node> records, HashMap<Node, NodeList> heads) {
        this.capacity = capacity;
        this.size = 0;
        this.headList = null;
        this.records = new HashMap<>();
        this.heads = new HashMap<>();
    }

    // 添加或修改
    public void set(int key, int value) {
        if (records.containsKey(key)) {  // 若key已经存在
            Node node = records.get(key);  // 得到其node
            node.times++;  // 频数+1
            node.value = value;  // 更新值
            NodeList curNodeList = heads.get(node);  // 得到其所在LinkList
            move(node, curNodeList);  // 将node从所在LinkList中删除并将频数更新后的node插入到合适的LinkList中
        }else {  // key不存在
            if (size == capacity) {  // 容量满了,说明要移除一个最久没使用的,那么headList指向的那串链表的tail即为待删除节点
                Node tail = headList.tail;
                headList.deleteNode(tail);
                modifieyHeadList(headList);  // 如果删除节点后这个链表为空了,那么就把整串链表删掉
                records.remove(tail.key);
                heads.remove(tail);
                size--;
            }

           Node newNode = new Node(key, value, 1);
           if (headList == null) {  // 若headList一个都没有则创建一个
               headList = new NodeList(newNode);
           }else {
               if (headList.head.times == 1) {  // 如果第一条链的频数是1,直接添加即可
                   headList.addNodeToHead(newNode);
               }else {  // 说明头链频数不是1,那么就新建一个
                   NodeList newList = new NodeList(newNode);
                   newList.next = headList;
                   headList.pre = newList;
                   headList = newList;
               }
           }
           records.put(key, newNode);
           heads.put(newNode, headList);
           size++;
        }
    }
    public boolean modifieyHeadList(NodeList nodeList) {
        if (nodeList.isEmpty()) {
            if (nodeList == headList) {  // 如果待删除那条链就是头链
                headList = nodeList.next;
                nodeList.next = null;
                if (headList != null) {
                    headList.pre = null;
                }
            }else {  // 待删除那条链不是头链
                nodeList.pre.next = nodeList.next;
                if (nodeList.next != null) {
                    nodeList.next.pre = nodeList.pre;
                }
            }
            return true;
        }
        return false;
    }

    public void move(Node node, NodeList oldNodeList) {
        oldNodeList.deleteNode(node);
        NodeList preList = modifieyHeadList(oldNodeList) ? oldNodeList.pre: oldNodeList;
        NodeList nextList = oldNodeList.next;

        if (nextList == null) {  // 如果插入位置为空
            NodeList newList = new NodeList(node);
            if (preList != null) {
                preList.next = newList;
            }
            newList.pre = preList;
            if (headList == null) {
                headList = newList;
            }
            heads.put(node, newList);
        }else {
            if (nextList.head.times == node.times) {  // 如果更新后的词频在nextList这条链中,直接添加
                nextList.addNodeToHead(node);
                heads.put(node, nextList);
            }else {  // 新建一条链插在pre和next之间
                NodeList newList = new NodeList(node);
                if (preList != null) {
                    preList.next = newList;
                }
                newList.pre = preList;
                newList.next = nextList;
                nextList.pre = newList;
                if (headList == nextList) {
                    headList = newList;
                }
                heads.put(node, newList);
            }
        }
    }

    public int get(int key) {
        if (!records.containsKey(key)) {
            return -999;
        }
        Node node = records.get(key);
        node.times++;
        NodeList curNodeList = heads.get(node);
        move(node, curNodeList);
        return node.value;
    }
}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值