栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【LeetCode】LRU缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【LeetCode】LRU缓存

题目链接:LRUCache

分析:LRU最近最久未使用,可以把每次刚被访问过的节点从缓存区的左端加入,那么缓存区右端就是最近最久未使用的节点,缓存区满了的话就从右端删除。get时,就把节点从原位置移除,再从左端加入缓存区;set时,就把节点从左端加入缓存区,如果缓存区满了,就从右端移除一个节点。

Java实现:哈希表+双向链表:

虽然有linkedHashMap结构,但还是需要自己实现双向链表结构。

代码如下:

//LRU缓存类:双向链表+HashMap(虽然java有自带的linkedHashMap(结合了哈希表与双向链表结构),但还是希望能够自己实现一个双向链表)
//最近被访问过的节点在链表头部
public class LRUCache {
//    内部还有一个类
    class DoublelinkedList{
        // 链表节点data区
        int key;
        int value;
        // 链表节点指针区
        DoublelinkedList prev;
        DoublelinkedList next;
        // 无参构造函数
        private DoublelinkedList(){};
        // 构造函数
        private DoublelinkedList(int key,int value){
            this.key=key;
            this.value=value;
        }
    }
//    LRUCache类的数据
    private int size;
    private int capacity;
    private Map cache=new HashMap<>();
    // 虚拟头尾节点,(添加和删除操作时不必再判断是否有相邻节点)
    private DoublelinkedList head,tail;

//    构造函数(初始化)
    public LRUCache(int capacity) {
        this.size=0;
        this.capacity=capacity;
        head=new DoublelinkedList();
        tail=new DoublelinkedList();
        head.next=tail;
        tail.prev=head;
    }
//    链表data域中的key和哈希表中的key值是相等的。(方便通过节点查找对应的key-value)
    public int get(int key) {
        DoublelinkedList node=cache.get(key);
        if(node==null)
            return -1;
        // 把刚访问过的节点移动到链表头部
        moveToHead(node);
        return node.value;
    }
    public void put(int key, int value) {
        DoublelinkedList node=cache.get(key);
        if(node==null){
            // 创建新节点
            node=new DoublelinkedList(key,value);
            // 加入哈希表
            cache.put(key,node);
            // 加入链表头部
            addToHead(node);
            //  还要判断当前size
            size++;
            if(size>capacity){
                // 删除链表尾部节点
                DoublelinkedList tailNode=removeTail();
                //  并从哈希表中删除
                cache.remove(tailNode.key);
                size--;
            }
        }
        else{
            // 更新值
            node.value=value;
            // 移动到链表头部
            moveToHead(node);
        }
    }
    private void addToHead(DoublelinkedList node){
        node.next=head.next;
        head.next.prev=node;
        head.next=node;
        node.prev=head;
    }
//    包括从当前位置删除和添加到链表头部
    private void moveToHead(DoublelinkedList node){
        removeNode(node);
        addToHead(node);
    }
    private void removeNode(DoublelinkedList node){
        node.prev.next=node.next;
        node.next.prev=node.prev;
        node.next=null;
        node.prev=null;
    }
    private DoublelinkedList removeTail(){
        DoublelinkedList node=tail.prev;
        node.prev.next=tail;
        tail.prev=node.prev;
        return node;
    }
}

Javascript实现:Map(Map的set方法加入数据是顺序加入的,即从尾部加入)

代码如下:

// 最近被访问过的节点在map尾部
// 构造函数
var LRUCache = function(capacity) {
    this.capacity=capacity;
    // map的set方法是按照顺序插入的(相当于从尾部插入)
    this.map=new Map();
};


LRUCache.prototype.get = function(key) {
    if(this.map.has(key)){
        let value=this.map.get(key);
        // 删除节点
        this.map.delete(key);
        // 再从尾部插入节点
        this.map.set(key,value);
        return value;
    }
    return -1;
};


LRUCache.prototype.put = function(key, value) {
    if(this.map.has(key)){
        this.map.delete(key);   
    }
    this.map.set(key,value);
    if(this.map.size>this.capacity){
        // 删除map中的第一个元素
        this.map.delete(this.map.keys().next().value);
    }
};

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644591.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号