HashMap+双向链表手写LRU缓存算法/页面置换算法

import java.util.Hashtable;
//https://zhuanlan.zhihu.com/p/34133067
class DLinkedList {
    String key; //键
    int value;    //值
    DLinkedList pre; //双向链表前驱
    DLinkedList next; //双向链表后继
}
public class LRUCache {
    private Hashtable<String,DLinkedList> cache = new Hashtable<String,DLinkedList>();
    private int count;
    private int capacity;
    private DLinkedList head, tail;
    public LRUCache(int capacity) {
        this.count = 0;
        this.capacity = capacity;
        head = new DLinkedList();
        head.pre = null;
        tail = new DLinkedList();
        tail.next = null;

        head.next = tail;
        tail.pre = head;
    }
    public int get(String key) {
        DLinkedList node = cache.get(key);
        if(node == null) return -1;
        this.moveToHead(node);
        return node.value;
    }
    public void set(String key,int value) {
        DLinkedList node = cache.get(key);
        if(node == null) {
            DLinkedList newNode = new DLinkedList();
            newNode.key = key;
            newNode.value = value;
            this.cache.put(key, newNode);
            this.addNode(newNode);
            ++count;

            if(count>capacity) {
                DLinkedList tail = this.popTail();
                this.cache.remove(tail.key);
                --count;
            }
        }
        else {
            node.value = value;
            this.moveToHead(node);
        }
    }
    private void addNode(DLinkedList node) {
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
    }
    private void removeNode(DLinkedList node) {
        DLinkedList pre = node.pre;
        DLinkedList next = node.next;
        pre.next = next;
        next.pre = pre;
    }
    private void moveToHead(DLinkedList node) {
        this.removeNode(node);
        this.addNode(node);
    }
    private DLinkedList popTail() {
        DLinkedList res = tail.pre;
        this.removeNode(res);
        return res;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        DLinkedList node = head;
        while(node != null){
            sb.append(String.format("%s:%s ", node.key,node.value));
            node = node.next;
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        LRUCache lru = new LRUCache(3);
        lru.set("1", 7);
        System.out.println(lru.toString());
        lru.set("2", 0);
        System.out.println(lru.toString());
        lru.set("3", 1);
        System.out.println(lru.toString());
        lru.set("4", 2);
        System.out.println(lru.toString());
        lru.get("2");
        System.out.println(lru.toString());
        lru.set("5", 3);
        System.out.println(lru.toString());
        lru.get("2");
        System.out.println(lru.toString());
        lru.set("6", 4);
        System.out.println(lru.toString());
        /*
         0ull:0 1:7 null:0
        null:0 2:0 1:7 null:0
        null:0 3:1 2:0 1:7 null:0
        null:0 4:2 3:1 2:0 null:0
        null:0 2:0 4:2 3:1 null:0
        null:0 5:3 2:0 4:2 null:0
        null:0 2:0 5:3 4:2 null:0
        null:0 6:4 2:0 5:3 null:0
         */
    }
}

原文地址:https://www.cnblogs.com/Roni-i/p/10340300.html

时间: 2024-11-02 12:05:18

HashMap+双向链表手写LRU缓存算法/页面置换算法的相关文章

操作系统 页面置换算法LRU和FIFO

LRU(Least Recently Used)最少使用页面置换算法,顾名思义,就是替换掉最少使用的页面. FIFO(first in first out,先进先出)页面置换算法,这是的最早出现的置换算法.该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最长的页面给予淘汰. FIFO置换算法有这样一个奇怪现象:内存空间块数越多,缺页中断率可能相反的越高(缺页中断次数越高). LFU(Least Frequently Used)最近最少使用算法,它是基于“如果一个数据在最近一段时间内使用次

操作系统页面置换算法(opt,lru,fifo,clock)实现

#include <iostream> #include<map> #include<set> #include <algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 200 using namespace std; int page[N];//页面引用号 int block[N];//物理块,内存 int dist[N][N];/

页面置换算法(最佳置换算法、FIFO置换算法、LRU置换算法、LFU置换算法)

页面置换产生的原因是:分页请求式存储管理(它是实现虚拟存储管理的方法之一,其中一个特性是多次性-->多次将页面换入或换出内存) 效果最好的页面置换算法:最佳置换算法 比较常用的页面置换算法有:FIFO置换算法.LRU置换算法.LFU置换算法 最佳置换算法:不可能实现-->是衡量其他置换算法的方法. FIFO置换算法:先进先出置换算法,淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰.(实现简单) LRU置换算法:最近最久未使用置换算法,该算法赋予每个页面一个访问字段,用来记录一

C#语言中的动态数组(ArrayList)模拟常用页面置换算法(FIFO、LRU、Optimal)

目录 00 简介 01 算法概述 02 公用方法 03 先进先出置换算法(FIFO) 04 最近最久未使用(LRU)算法 05 最佳置换算法(OPT) 00 简介 页面置换算法主要是记录内存的忙闲状态,为进程分配和释放内存.当主存的空间太小而无法装入所有的进程时,就需要在内存和硬盘之间进行调度操作. 多数操作系统只采用某种特定的页面置换算法进行置换,无法预先探测当前运行进程的页面访问模式,因此不能根据不同的页面访问模式,选用不同的页面置换算法.当然,如果能对不同的访问模式选取相应的页面置换算法,

操作系统之页面置换算法(最佳置换OPT,先进先出FIFO,最近最久未使用LRU)

最近学习操作系统时,实验要求实现常见的三种页面置换算法,博主按照书上要求试着编写,实现了案例,并记录在博客随记中,以便后续自己复习并也给需要的同学分享参考一下!水平有限,若有错,请悄悄告诉博主!博主好立即改正. 最佳置换算法(optimal replacement,OPT)是从内存中选择今后不再访问的页面或者在最长一段时间后才需要访问的页面进行淘汰.如下例子: 1 #include <iostream> 2 #include <stdio.h> 3 #include <std

操作系统原理(二)——内存管理之页面置换算法

页面置换算法 1. 总述 为提高内存利用率,解决内存供不应求的问题,更加合理的使用内存,人们创造了分页式内存抽象.同时有一个虚拟内存的概念,是指将内存中暂时不需要的部分写入硬盘,看上去硬盘扩展了内存的容量,所以叫做“虚拟”内存.使用虚拟内存,应用程序可以使用比实际物理内存更大的内存空间.可以认为这个更大的内存空间就在硬盘上,只有将某一部分需要被用到时,才被写入真实内存:当它暂时不再被用到时,又被写回硬盘.分页式内存管理将物理内存分为等大的小块,每块大小通常为1K.2K.4K等,称为页帧:逻辑内存

[Operate System &amp; Algorithm] 页面置换算法

页面置换算法是什么?我们看一下百度百科对页面置换算法给出的定义:在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断.当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存中选择一个页面将其移出内存,以便为即将调入的页面让出空间.而用来选择淘汰哪一页的规则叫做页面置换算法.好了,说到底,页面置换算法就是因为操作系统的内部不够,在调入新的页面时如何取代哪个页面的问题.常见的页面置换算法有如下图所示几种: 上述的随机替换我们很容易理解,就是操作系统随机挑选的一个被

虚存管理页面置换算法 — FIFO和RUL算法模拟实现

本篇博文为追忆曾经写过的算法系列第一篇(20081021) 温故知新 目的: 为了解决内存容量有限与多作业运行的冲突,运用了虚拟存储技术,能从逻辑上对内存进行扩充,达到扩充内存的效果.分页存储管理是实现虚拟存储的一种方案.通过模拟算法的实验,加深理解,虚拟存储器的基本原理和方法. 要求: 1.请求分页的置换算法(FIFO && RUL算法实现):2.按给定的顺序列,输出页面调度过程包括命中 / 缺页,调入/调出:3.计算缺页率,频率. 说明: vp_list[N] //访问序列 bs[M]

操作系统中10种页面置换算法的总结

页面置换算法总结 当发生缺页中断时,操作系统必须将内存中选择一个页面置换出去为要调入的新页面腾出空间. 那究竟选择哪一个淘汰哪一个一面比较好呢? 1.      最优页面置换算法 选择最长时间内不会被访问的页面丢掉.越久越好.但是理论上不能实现. 2.      最近未使用页面置换算法(NRU)算法 找到最久没有使用的页面置换出去,页面被访问时设置R位,修改时设置M位,R位定期清0: 把页面分四类 0类.未被访问,未被修改的R=M=0 1类未被访问,被修改R=0,M=1 2类被访问,未被修改R=