【数据结构】LRU的实现

最近看到好多人的面试题都是要求手写LRU,自己也想整理下这方面的知识点

页面置换算法:地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。

LRU算法:最近最少使用,简单来说就是将数据块中,每次使用过的数据放在数据块的最前端,然后将存在的时间最长的,也就是数据块的末端的数据剔除掉这就是LRU算法

有一种叫做有序字典的数据结构,综合了哈希表和链表,在 Python 中为 OrderedDict,在 Java 中为 LinkedHashMap。

from collections import  OrderedDict


class LRUCache(OrderedDict):
    def __init__(self, capacity: int):
        self.capacity = capacity
    def get(self, key: int) -> int:
        if key not in self:
            return -1
        self.move_to_end(key)
        return self[key]


    def put(self, key: int, value: int) -> None:
        if key in self:
            self.move_to_end(key)
        self[key] = value
        if len(self) > self.capacity:
            self.popitem(last=False)


package com.example.write;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

public class LRU extends LinkedHashMap<String,String>{
    private  int capacity;

    public LRU(int capacity){
        super(capacity,0.75F,true);
        this.capacity = capacity;
    }

    public String get(int key){
        return super.getOrDefault(key,"-1");
    }


    public String put(String key, String value){
        return super.put(key,value);
    }

	//判断是否删除最老数据的方法,默认是返回false
    @Override
    protected boolean removeEldestEntry(Map.Entry<String,String> entry){
        return size() > capacity;
    }

    public static void main(String[] args) {

//        Map<String, String> linkedHashMap = new LinkedHashMap<>(4, 0.75f, true);
//        linkedHashMap.put("1","1");
//        linkedHashMap.put("2","2");
//        linkedHashMap.put("3","3");
//        linkedHashMap.put("4","3");
//        linkedHashMap.put("5","3");
//        linkedHashMap.put("6","3");
//        linkedHashMap.lruput("7","3");
//
//        linkedHashMap.get("1");
//        Iterator<Map.Entry<String,String>> iterator = linkedHashMap.entrySet().iterator();
//        while (iterator.hasNext()){
//
//            Map.Entry<String,String> entry = iterator.next();
//            System.out.println("key="+ entry.getKey() + ",value=" + entry.getValue());
//
//        }
        LRU lru = new LRU(3);
        lru.put("1","1");
        lru.put("2","2");
        lru.put("3","3");
        lru.put("4","4");
        lru.get("2");
        Iterator<Map.Entry<String,String>> iterator = lru.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String,String> entry = iterator.next();
            System.out.println("key="+ entry.getKey() + ",value=" + entry.getValue());
        }
    }

}

方法二 :哈希表 + 双向链表

package com.example.write;

import java.util.HashMap;

public class LRU2 {

    class Node{
        int key;
        int val;
        Node prev;
        Node next;

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

    }

    private HashMap<Integer,Node> res;

    private Node head;

    private int size;

    private int capacity;

    public LRU2(int capacity){
        head = new Node(0,0);
        head.next = null;
        head.prev = null;
        size = 0;
        this.capacity = capacity;

        res = new HashMap<>(capacity);
    }

    public int get(int key){
        if(res.containsKey(key)){
            Node tmp = res.get(key);
            tmp.prev.next = tmp.next;

            if(tmp.next != null){
                tmp.next.prev = tmp.prev;
            }

            tmp.next = head.next;
            tmp.prev = head;

            if(head.next !=null){
                head.next.prev = tmp;
            }

            head.next = tmp;

            return res.get(key).val;
        }
        return -1;
    }

    public void put(int key,int value){
        if(res.containsKey(key)){
            Node tmp = head.next;
            while(tmp != null){
                if(tmp.key == key){
                    tmp.val = value;
                    tmp.prev.next = tmp.next;
                    if(tmp.next != null){
                        tmp.next.prev = tmp.prev;
                    }
                    tmp.next = head.next;
                    tmp.prev = head;
                    if(head.next != null){
                        head.next.prev = tmp;
                    }
                    head.next = tmp;
                    return;
                }
                tmp = tmp.next;
            }
        }else{
            if(size == capacity){
                Node tmp = head.next;
                while(tmp.next !=null){
                    tmp = tmp.next;
                }
                res.remove(tmp.key);
                tmp.prev.next = null;
                tmp = null;
                size--;
            }

            size++;
            Node temp = new Node(key,value);
            temp.next = head.next;
            temp.prev = head;
            if(head.next != null){
                head.next.prev = temp;
            }
            head.next = temp;
            res.put(key,temp);

        }
    }
}

双端链表 加 双端队列


public class Test {

    class LRUnode{
        String key;
        String value;
        LRUnode prey;
        LRUnode next;
        public LRUnode(String key,String value){
            this.key =key;
            this.value = value;
        }

    }

    private  HashMap<String,LRUnode> map ;
    private  int capacity;
    private  LRUnode head;
    private  LRUnode tail;
    public Test(int capacity){
        this.capacity = capacity;
        map = new HashMap<>();
        head = null;
        tail = null;

    }
    public String get(String key){
        LRUnode node = map.get(key);
        remove(node,false);
        setHead(node);
        return node.value;
    }
    
    public void set(String key,String value){
        LRUnode tmpnode = null;
        if(map.containsKey(key)){
            tmpnode = map.get(key);
            tmpnode.value = value;
            remove(tmpnode,false);
        }else{
            if(map.size() == capacity){
                remove(tail,true);
            }
            tmpnode = new LRUnode(key,value);
            map.put(key,tmpnode);
        }

        setHead(tmpnode);

    }

    private void setHead(LRUnode node){
        if(head != null){
            node.next = head;
            head.prey = node;
        }
        head = node;
        if(tail == null){
            tail = node;
        }
    }
    
    //flag 是要不要删除map里的key
    private void remove(LRUnode node,Boolean flag){
        if(node.prey != null){
            node.prey.next = node.next;
        }else{
            head = node.next;

        }
        if(node.next != null){
            node.next.prey = node.prey;
        }else{
            tail = node.prey;
        }
        node.next = null;
        node.prey = null;
        if(flag){
            map.remove(node.key);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值