`

LRU算法模拟实现

    博客分类:
  • java
 
阅读更多

LRU (移除最少使用内存)

模拟算法

语言:JAVA

数据结构:HASH+双向链表

原则:

 1)最少使用的是链表头(removeLRUNode)

 2)最近使用的放在链表尾(get)

 3)最近添加或更新值放在链表尾(add)

 4)节点有变化,节点的前后节点互联

 

 

package test.lrucache;

import java.util.HashMap;

public class LRUCache {

    private HashMap<String, LinkedNode> nodeMap = new HashMap<>();

    private LinkedNode rootNode;
    private LinkedNode bottomNode;

    /**
     * 添加一个新节点,如果节点已存在,则覆盖值并移至链表最后
     * @param key
     * @param value
     */
    public void add(String key, Object value) {
        LinkedNode node = get(key);
        if (node != null) {
            nodeMap.get(key).setValue(value);
        } else {
            if (bottomNode == null) {
                rootNode = bottomNode = new LinkedNode(key, value, null, null);
            } else {
                node = new LinkedNode(key, value, bottomNode, null);
                bottomNode.setAftNode(node);
                bottomNode = node;
            }
            nodeMap.put(key, bottomNode);
        }
    }

    /**
     * 获取一个节点,并移至链表最后
     * @param key
     * @return
     */
    public LinkedNode get(String key) {
        LinkedNode node = nodeMap.get(key);
        if (node != null) {
            if (rootNode != bottomNode && node != bottomNode) {
                updatePreAndAftNode(node);
                node.setPreNode(bottomNode);
                node.setAftNode(null);
                bottomNode.setAftNode(node);
                bottomNode = node;
            }
        }
        return node;
    }


    /**
     * 删除指定节点
     * @param key
     * @return
     */
    public LinkedNode remove(String key) {
        LinkedNode node = nodeMap.remove(key);
        if (node != null) {
            updatePreAndAftNode(node);
            if (node.isRootNode()) {
                rootNode = node.getAftNode();
            }
            if (node.isBottomNode()) {
                bottomNode = node.getPreNode();
            }
        }
        return node;
    }

    /**
     * 删除最少使用的节点
     */
    public void removeLRUNode() {
        remove(rootNode.getKey());
    }

    /**
     * 打印链表
     */
    public void printAllNode() {
        if (rootNode == null)
            return;
        LinkedNode curNode = rootNode;
        System.out.print(curNode.getValue() + "\t");
        while ((curNode = curNode.getAftNode()) != null) {
            System.out.print(curNode.getValue() + "\t");
        }
        System.out.println();
    }

    /**
     * 反转打印链表
     */
    public void revePrintAllNode() {
        if (bottomNode == null)
            return;
        LinkedNode curNode = bottomNode;
        System.out.print(curNode.getValue() + "\t");
        while ((curNode = curNode.getPreNode()) != null) {
            System.out.print(curNode.getValue() + "\t");
        }
        System.out.println();
    }

    /**
     * 对节点的前后节点创建连线
     * @param node
     */
    private void updatePreAndAftNode(LinkedNode node) {
        //整个链表只有一个节点
        if (node.isSingleNode()){
            return;
        }
        //是根节点
        if (node.isRootNode()) {
            node.getAftNode().setPreNode(null);
            rootNode = node.getAftNode();
        }
        //是尾节点
        else if(node.isBottomNode()) {
            node.getPreNode().setAftNode(null);
            bottomNode = node.getPreNode();
        }
        //是中间节点
        else{
            node.getPreNode().setAftNode(node.getAftNode());
            node.getAftNode().setPreNode(node.getPreNode());
        }

    }


    public static void main(String[] args) {
        LRUCache cache = new LRUCache();
        for (int i = 0; i < 10; i++) {
            cache.add("key" + i, i);
        }
        System.out.println("初始化节点key0-9");
        cache.printAllNode();

        System.out.println("删除尾节点key9");
        cache.remove("key9");
        cache.printAllNode();

        System.out.println("删除不存在的节点key10,链表不变");
        cache.remove("key10");
        cache.printAllNode();

        System.out.println("删除根节点key0");
        cache.removeLRUNode();
        cache.printAllNode();

        System.out.println("添加key10=10");
        cache.add("key10", 10);
        cache.printAllNode();

        System.out.println("使用key5,key5移到最后");
        cache.get("key5");
        cache.printAllNode();

        System.out.println("添加存的节点key10=-10,覆盖原值,并且移到最后");
        cache.add("key10", -10);
        cache.printAllNode();


        System.out.println("使用根节点key1,key1移到最后");
        cache.get("key1");
        cache.printAllNode();

        System.out.println("删除中间节点key7");
        cache.remove("key7");
        cache.printAllNode();

        System.out.println("反转打印链表");
        cache.revePrintAllNode();

        System.out.println("只保留8节点");
        cache.remove("key2");
        cache.remove("key3");
        cache.remove("key4");
        cache.remove("key6");
        cache.remove("key5");
        cache.remove("key10");
        cache.remove("key1");
        cache.printAllNode();
        cache.revePrintAllNode();

        System.out.println("8节点也删除");
        cache.remove("key8");
        cache.printAllNode();
        cache.revePrintAllNode();

    }


}

 

 

package test.lrucache;


public class LinkedNode {
    private String key;
    private Object value;
    private LinkedNode preNode;
    private LinkedNode aftNode;

    public LinkedNode(String key, Object value, LinkedNode preNode, LinkedNode aftNode) {
        this.key = key;
        this.value = value;
        this.preNode = preNode;
        this.aftNode = aftNode;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public LinkedNode getPreNode() {
        return preNode;
    }

    public void setPreNode(LinkedNode preNode) {
        this.preNode = preNode;
    }

    public LinkedNode getAftNode() {
        return aftNode;
    }

    public void setAftNode(LinkedNode aftNode) {
        this.aftNode = aftNode;
    }

    public boolean isRootNode() {
        return this.preNode == null;
    }

    public boolean isBottomNode(){
        return this.aftNode == null;
    }

    public boolean isSingleNode() {
        return isRootNode() && isBottomNode();
    }

    public void clear() {
        setAftNode(null);
        setPreNode(null);
        setValue(null);
    }


}

 

控制台:
-------------------------------------------------------------
初始化节点key0-9
0	1	2	3	4	5	6	7	8	9	
删除尾节点key9
0	1	2	3	4	5	6	7	8	
删除不存在的节点key10,链表不变
0	1	2	3	4	5	6	7	8	
删除根节点key0
1	2	3	4	5	6	7	8	
添加key10=10
1	2	3	4	5	6	7	8	10	
使用key5,key5移到最后
1	2	3	4	6	7	8	10	5	
添加存的节点key10=-10,覆盖原值,并且移到最后
1	2	3	4	6	7	8	5	-10	
使用根节点key1,key1移到最后
2	3	4	6	7	8	5	-10	1	
删除中间节点key7
2	3	4	6	8	5	-10	1	
反转打印链表
1	-10	5	8	6	4	3	2	
只保留8节点
8	
8	
8节点也删除

	

Process finished with exit code 0

 

分享到:
评论

相关推荐

    虚拟存储中页面调度算法的模拟实现fifo ,lru opt

    在这个项目中,我们关注的是虚拟存储中的页面调度算法,具体包括FIFO(先进先出)、LRU(最近最少使用)以及OPT(最佳页面替换)这三种算法的模拟实现。 1. FIFO(先进先出)算法是最简单的页面替换策略。当内存满...

    LRU算法模拟实验

    实验目的是通过编程模拟LRU算法的工作过程,帮助学生理解页面调度和页面置换算法,特别是LRU算法的实现细节。实验前需要学习虚拟存储管理、页面调度等相关概念,以及LRU、FIFO、LFU等常见页面调度算法的基本思想。 ...

    Java实现LRU算法.zip

    在Java中实现LRU算法,通常会使用数据结构如HashMap或LinkedHashMap来存储页面及其访问信息。HashMap提供快速的查找操作,而LinkedHashMap则同时保持了插入顺序,这对于实现LRU至关重要,因为我们需要快速找到最近...

    c语言实现的LRU算法

    在C语言中实现LRU算法,需要理解数据结构和算法的基础知识,以及如何在C语言中有效地管理内存。 首先,LRU算法的核心是数据结构的选择。通常使用双向链表来存储数据,因为双向链表允许我们快速地插入和删除元素,...

    东南大学操作系统实验——实现LRU算法及其近似算法

    实验内容包括实现LRU算法的两种不同变体:计数器实现和栈实现。在计数器实现中,每个页面都有一个访问计数器,每当页面被访问时,计数器增加,淘汰时选择计数最小的页面。而在栈实现中,页面按访问顺序存储在栈中,...

    lru算法C语言实现

    ### LRU算法C语言实现详解 #### 一、引言 LRU(Least Recently Used,最近最少使用)算法是一种常用的数据缓存淘汰策略,在计算机科学领域应用广泛,尤其是在操作系统、数据库管理和Web服务器缓存管理等方面。本文...

    lru算法实验报告

    实验报告中,学生被要求用 C 或 C++ 编写程序来模拟 LRU 页面置换算法。实验的主要目标包括理解和实现 LRU 算法的调度过程,并计算出访问页面时的命中率。 实验内容分为以下部分: 1. 设计一个虚拟存储系统,其中...

    lru算法和fifo算法模拟

    LRU算法和FIFO算法合体

    LRU算法实现_实验报告

    然而,这个简单的C语言实现提供了一个直观的理解基础,展示了LRU算法的基本操作和逻辑。通过这样的实验,学生可以深入理解页面替换策略的工作原理,并为进一步学习操作系统和内存管理打下坚实的基础。

    实验四:LRU算法的模拟

    模拟页式虚拟存储管理中硬件地址变换和缺页中断,并用LRU算法处理缺页中断

    一个LRU算法的实现

    在这个实验设计课程中,我们将探讨LRU算法的原理和实现。 首先,我们需要理解LRU算法的核心思想。假设有一个固定大小的缓存(或内存),当新的数据请求进来而缓存已满时,LRU算法会选择最近最少使用的数据进行替换...

    操作系统之LRU算法(java)(csdn)————程序.pdf

    操作系统之LRU算法(Java) LRU(Least Recently Used,最近最少使用)算法是一种常用的页面置换算法,用于操作系统中管理内存页面。该算法的基本思想是:当进程在 CPU 上运行时,如指令中涉及逻辑地址时,操作系统...

    进程调度、银行家算法、页式地址重定位模拟,LRU算法模拟和先来先服务算法代码

    进程调度、银行家算法、页式地址重定位...本文对操作系统中进程调度、银行家算法、页式地址重定位模拟、LRU 算法模拟和先来先服务算法代码进行了详细的分析和实现。这些知识点对于操作系统的学习和开发具有重要的意义。

    LRU算法(操作系统)

    `queue`类表示一个队列,用于模拟LRU算法中的页面队列。队列包含两个指针`front`和`rear`分别指向队列的前端和后端,并且有一个静态成员变量`count`记录队列中的元素数量。 ```cpp class queue { friend class LRU...

    模拟LRU算法

    2. **数据结构实现**:通常,LRU算法会用到一种数据结构——双向链表和哈希表。双向链表可以方便地按照访问顺序移动页面,而哈希表则用于快速查找页面。 - **双向链表**:新访问的页面被添加到链表头部,表示其是...

    调度算法中的经典-LRU算法的实现(绝对值得收藏)

    在C语言实现LRU算法时,通常需要维护一个数据结构来记录每个页面的访问信息,如访问时间戳或者访问计数。一个常见的方法是使用链表,每个节点代表一个页面,链表的顺序表示页面的访问顺序。每当有新的页面被访问,...

    LRU 算法(c语言)

    ### LRU算法(Least Recently Used)在C语言中的实现 #### 概述 LRU算法是一种常用的缓存淘汰策略,在计算机科学中广泛应用于操作系统、数据库系统以及Web浏览器等场景。其核心思想是当缓存满时,优先淘汰最近最少...

    操作系统LRU算法实验报告

    在电子科技大学的这个实验报告中,学生需要设计并改进LRU算法的实现。实验的目标是让用户自定义页块数量和页面访问序列,然后模拟页面访问过程,计算缺页次数和缺页率。实验的具体内容是根据一个给定的20位长页面...

    LRU页面淘汰算法模拟程序(源码)C++

    LRU页面淘汰算法模拟程序(源码)C++ 产生一个进程的大小,构建页表并对页表进行初始化,随后生成访问的指令地址流(是一系列需要访问的指令的地址)。不失一般性,可以适当地(人工指定或随机数产生器)生成这个序列...

    页面置换算法LRU(模拟页面管理)

    页面置换算法LRU(模拟页面管理)  用高级语言编写一个页面置换算法LRU的模拟程序。  设置恰当的数据结构,有效存储数据。   动态输入存储区块数、作业调度序列。  输出分配结果、置换过程以及其它相关的...

Global site tag (gtag.js) - Google Analytics