LRU的双链表的简单实现(小白写法)

先给一个节点类,属性有:节点值(我用的int类型数值为例),前节点,后节点。前节点主要功能是便于不用遍历的方式寻找前节点,以免多次遍历造成时间复杂度的增长。

public class Node {
    int value;
    Node next;
    Node pre;
    }

提供一个构造方法,去建立链表头

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

提供两种add方式,方便不同的情况插入

    public Node add(int value) {
        Node node = new Node(value);
        return add(node);
    }
    
	//对于直接插入节点,要注意前后节点的更改
    public Node add(Node node) {
        next = node;
        node.pre = this;
        return next;
    }

重写toString方法,方便查看节点值

    @Override
    public String toString() {
        if (this.next == null) {
            return ""+value;
        }
        return value+"-->"+this.next.toString();
    }

开始写LRU(最大缓存区为100)

class LRU {
	//头节点
    Node node;
    int sizeMax = 100;
    int size = 0;
    //尾节点指针(不是实时的,有时需要方法调用来寻找最新的尾节点)
    Node lastNode;

	//构造方法,建立链表头
    public LRU(int value) {
        node = new Node(value);
        lastNode = node;
        this.size++;
    }

	//寻找尾节点的方法,从已有尾节点开始往后寻找
    void lastNode() {
        Node node = this.lastNode;
        while (node.next != null) {
            node = node.next;
        }
        lastNode= node;
    }

	//检查值为value的节点值是否存在
    Node valueCheck(int value) {
        Node x = this.node;
        do {
            if (x.value == value) {
                return x;
            }
            x = x.next;
        } while (x != null);
        return null;
    }

	//添加操作,
	//遍历链表,判断待添加的数据时候已经存在
	//存在: 删除该节点,然后在头节点添加。
	//不存在:
	//  1. 缓存没满:在头节点添加
	//	2. 缓存满了,删除最后一个节点,然后在头节点添加
    void add(int value) {
        Node valueCheck = valueCheck(value);
        //如果valueCheck不是空的话,说明value存在,删除该节点,
        if (valueCheck != null) {
            delete(valueCheck);
        } else {
        //否则的话,就建立值为value的Node	
            valueCheck = new Node(value);
        }
        //判断是否超出缓存大小
        if (size >= sizeMax) {
            lastNode();
            delete(lastNode);
        }
        //因为是头节点添加所以是valueCheck添加node,再将valueCheck赋值给node,
        //并将头节点的前节点置为null
        valueCheck.add(this.node);
        this.node = valueCheck;
        this.node.pre = null;
        //最后将size+1
        this.size++;
    }

	//删除节点,因为该方法是类体自己调用的,所以不需要判断是否存在(因为只有存在才调用)
    private void delete(Node node) {
    	//先将缓存数减一
        this.size--;
        //将尾节点指针放到尾节点上
        lastNode();
        if (node == lastNode) {
        	//如果是尾节点,那么只需要将尾节点指针前移
        	//这一步只是为了移动尾节点指针
            lastNode = lastNode.pre;
        }
        if (node.pre == null) {
        	//如果是头节点,那么只需要将头节点指针后移,并将前节点置为null
            node.next.pre = null;
            this.node = node.next;
            return;
        } else if (node.next == null) {
        	////如果是尾节点,那么只需要将尾节点前指针的后节点置为null
            node.pre.next = null;
            return;
        }
        //如果是中间节点的话,就正常断前后链
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

在这里插入图片描述

	//删除某个节点值为value的节点
    void delete(int value) {
    	//先检查是否存在
        Node valueCheck = valueCheck(value);
        if (valueCheck == null) {
        	//如果不存在就退出
            return;
        }
        //存在的的话就删除
        delete(valueCheck);
    }

	//寻找某个节点值为value的节点
    void find(int value) {
        Node valueCheck = valueCheck(value);
        if (valueCheck != null) {
            delete(valueCheck);
            valueCheck.add(node);
            node = valueCheck;
            node.pre = null;
        }
    }

	//重写toString方法,直接用Node写好的toString就可以
    @Override
    public String toString() {
        return "node=" + node;
    }
}

基本基于双链表的LRU就是实现了,主要就是对LRU的认识,LRU就是把最近用的放到最前面,最不常用的放在最后,等到因为缓存慢需要删除的时候,优先删除最后一个节点。

发布了8 篇原创文章 · 获赞 6 · 访问量 329

猜你喜欢

转载自blog.csdn.net/qq_43587378/article/details/105386525