[原创]LRU算法的简单实现(基于Java链表)

[原创]LRU算法的简单实现(基于Java链表)

最近最久未使用(LRU,Least Recently Used)算法,是操作系统中一种常用的页面置换策略。

例如下图,对于序列

{1, 8, 1, 7, 8, 2, 7, 2, 1, 8, 3, 8, 2, 1, 3, 1, 7, 1, 3, 7}

最终留在缓存中的页面是2,1,3,7.

今天使用链表简单实现了一下,我的思路是,在页面调度的过程中,维护一个单链表结构,当有新页面出现时,如果链表未达最大缓存容量,将新页面直接挂在链表尾部;如果缓存已满,需要先遍历缓存中的页面,查看新页面是否命中缓存。

如果命中,则将链表中命中的页面删除,并将新页面挂在链表尾部;若未命中,将链表起始结点删除,再将新页面挂在链表尾部。

代码如下:

LRU

class LRU {
    private class Node {
        Node next;
        int val;

        public Node(int val) {
            this.val = val;
        }
    }
    //缓存容量
    private int cap;
    //首结点
    private Node head;

    public LRU(int cap) {
        this.cap = cap;
    }

    //获取链表长度
    public int getLength() {
        int length = 0;
        Node temp = head;
        while (temp != null) {
            temp = temp.next;
            length++;
        }
        return length;
    }

    //插入节点
    public void put(int e) {
        Node node = new Node(e);
        Node temp = head;
        //空结点,直接插入
        if (head == null) {
            head = node;
            //结点未满时,插入到末尾
        } else if (this.getLength() < cap) {
            while (temp.next != null) {
                temp = temp.next;
            }
            temp.next = node;
            //结点(页面)满时,分两种情况:1,新结点未命中,删除头结点,增加尾结点;2,新结点命中,将命中结点删除,并将命中结点添加在末尾
        } else {
            int count = 0;
            //命中页面的序号
            int index = -1;
            //是否命中
            boolean flag = false;
            while (temp != null) {
                if (temp.val == e) {
                    flag = true;
                    index = count;
                    break;
                }
                count++;
                temp = temp.next;
            }
            //情况1
            if (flag) {
                //头结点为命中的结点
                if (index == 0) {
                    head = head.next;
                    //否则,查找命中结点并删除
                } else {
                    int i = 0;
                    Node temp2 = head;
                    while (temp2 != null) {
                        if (i == index - 1) {
                            temp2.next = temp2.next.next;
                            break;
                        }
                        i++;
                        temp2 = temp2.next;
                    }
                }
            }
            //情况2
            else {
                //删除头结点
                head = head.next;
            }
            //添加尾结点
            Node temp1 = head;
            while (temp1.next != null) {
                temp1 = temp1.next;
            }
            temp1.next = node;

        }
    }
    //打印缓存中的页面
    public void printList() {
        if (head == null) {
            System.out.println("空");
        } else {
            Node temp = head;
            while (temp != null) {
                System.out.print(temp.val + " ");
                temp = temp.next;
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        LRU lru = new LRU(4);
        int[] input = new int[]{1, 8, 1, 7, 8, 2, 7, 2, 1, 8, 3, 8, 2, 1, 3, 1, 7, 1, 3, 7};
        for (int e : input) {
            lru.put(e);
        }
        lru.printList();
    }
}

打印结果:

如果想要提高访问效率,可以采用HashMap等结构辅助记录结点所在位置。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值