利用HashMap和双向链表实现LRU(最近最久未被使用)算法(LeetCode146题)

利用HashMap和双向链表实现LRU(最近最久未被使用)算法


一个场景,缓存机制,(用双向链表维护缓存区域,头节点为最久未被访问节点,尾节点为最近被访问的节点),缓存有限,优先替换出头节点,最近被访问的放到尾节点。
HashMap的作用:链表删除添加节点的时间复杂度为O(1),但是找到元素的时间复杂度为O(n),通过HashMap实现O(1)复杂度的节点查找。
不过多解释了,直接上代码了,不懂可以直接留言。

class LRUCache {
    HashMap<Integer, Node> hashMap;
    int capacity = 0;
    Node head = null;
    Node tile = null;
    public LRUCache(int capacity) {
        hashMap = new HashMap();
        this.capacity = capacity;
    }
    
    public int get(int key) {
        if (hashMap.containsKey(key)) {
            Node node = hashMap.get(key);
            moveToTile(node);
            return node.value;
        }
        return -1;
        
    }
    
    public void put(int key, int value) {
        //先看HashMap是否存在
        if (hashMap.containsKey(key)) {
            Node node = hashMap.get(key);
            node.value = value;
            moveToTile(node);
        }else {
        	//hashmap里面不存在的话,如果尾巴节点为空,则构造头节点和尾节点
            if (tile == null) {
                head = tile = new Node(null, null, key, value);
                hashMap.put(key, head);
            }else {
            	//如果尾巴节点不为空,直接在尾部追加,
            	//不要忘记,假如已经达到最大容量,则需要去掉头节点
                removeEldest();
                Node node = new Node(tile, null, key, value);
                tile.next = node;
                tile = node;
                hashMap.put(key, node);
            }
        }
    }
	//把一个节点移动到链表尾巴
    public void moveToTile (Node node) {
        if (node == tile) return;
        if (node == head) {
            head = head.next;
            head.pre = null;
            
            tile.next = node;
            node.pre = tile;
            node.next = null;
            tile = node;
            
        }else {
            node.pre.next = node.next;
            node.next.pre = node.pre;

            tile.next = node;
            node.pre = tile;
            node.next = null;
            tile = node;
        }
    }
	//移除最老的节点,即头节点
    public void removeEldest () {
        if (hashMap.size() == capacity) {
            hashMap.remove(head.key);
            Node node = head;
            head = head.next;
            if (head != null) head.pre = null;
            node.next = null;
        }
    }

    class Node {
        Node pre;
        Node next;
        int key;
        int value;
        public Node () {}
        public Node(Node pre, Node next, int key, int value) {
            this.pre = pre;
            this.next = next;
            this.key = key;
            this.value = value;
        }
    }
}

下面的不用啊看了,因为是之前写的,可能比较乱,上面的比较清楚!

public class DoubleLinkedList implements Iterable<Integer>{
    private Node first;
    private Node head;
    private Node tile;
    private int maxValue;
    private int size;
    private HashMap<Integer,Node> hashMap;
    public DoubleLinkedList(int maxValue){
        this.first = new Node(0);
        this.head = null;
        this.tile = null;
        this.maxValue = maxValue;
        this.size = 0;
        this.hashMap = new HashMap<Integer, Node>();
    }
    public int size(){
        return size;
    }
    public void put(int value){
        Node node = new Node(value);
        if (size==0){
            first.next = node;
            node.pre = first;
            head = node;
            tile = node;
            hashMap.put(value,node);
            size++;
        }else{

            //缓存中已经存在该value
            if(get(value) != -1){
                Node node1 = hashMap.get(value);
                if(tile != node1){
                    //摘除 放到尾巴
                    Node before = node1.pre;
                    Node after = node1.next;
                    before.next = after;
                    after.pre = before;

                    tile.next = node1;
                    node1.pre = tile;
                    //下面这步很重要 一定要将next置空 不然会出现循环指针
                    node1.next = null;
                    tile = node1;
                }

            }
            //缓存中不存在该value
            else {
                //缓存已经满了
                if(size == maxValue){
                    //去掉头节点
                    //并且从hashMap中除去
                    hashMap.remove(head.value);
                    Node node2 = head.next;
                    first.next = node2;
                    node2.pre = first;
                    head = node2;

                    //元素放到尾节点
                    tile.next = node;
                    node.pre = tile;
                    tile = node;
                }
                //缓存没有满
                else {
                    //直接放到为节点
                    tile.next = node;
                    node.pre = tile;
                    tile = node;
                    size++;
                }

                //放到hashmap中
                hashMap.put(value,node);
            }
        }

    }
    public int get(int value){
        if(hashMap.containsKey(value)){
            return value;
        }
        return -1;

    }

    public Iterator<Integer> iterator() {
        return new DoubleIterator();
    }
    private class DoubleIterator implements Iterator<Integer>{
        Node node = first;
        private DoubleIterator(){

        }

        public boolean hasNext() {
            if(node.next != null){
                return true;
            }
            return false;
        }

        public Integer next() {
            node = node.next;
            return node.value;
        }

        public void remove() {

        }


    }



    private class Node{
        private Node pre;
        private Node next;
        private int value;
        private Node(int value){
            this.value = value;
            this.pre = null;
            this.next = null;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值