缓存算法(页面置换算法)-FIFO、LFU、LRU

1. FIFO -- 先进先出

如果一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。

实现:

利用一个双向链表保存数据,当来了新的数据之后便添加到链表末尾,如果Cache存满数据,则把链表头部数据删除,然后把新的数据添加到链表末尾。在访问数据的时候,如果在Cache中存在该数据的话,则返回对应的value值;否则返回-1。如果想提高访问效率,可以利用hashmap来保存每个key在链表中对应的位置。

 

2. LFU -- 最近最少使用

基于“如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路。

LFU是基于访问次数的。

实现:

为了能够淘汰最少使用的数据,LFU算法最简单的一种设计思路就是利用一个数组存储数据项,用hashmap存储每个数据项在数组中对应的位置,然后为每个数据项设计一个访问频次,当数据项被命中时,访问频次自增,在淘汰的时候淘汰访问频次最少的数据。这样一来的话,在插入数据和访问数据的时候都能达到O(1)的时间复杂度,在淘汰数据的时候,通过选择算法得到应该淘汰的数据项在数组中的索引,并将该索引位置的内容替换为新来的数据内容即可,这样的话,淘汰数据的操作时间复杂度为O(n)。

  另外还有一种实现思路就是利用小顶堆+hashmap,小顶堆插入、删除操作都能达到O(logn)时间复杂度,因此效率相比第一种实现方法更加高效。

 

3. LRU -- 最近最久未使用

如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

实现:

(1)用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已满时,将时间戳最大的数据项淘汰。

思路简单,但是需要不停地维护数据项的访问时间戳,另外,在插入数据、删除数据以及访问数据时,时间复杂度都是O(n)。

(2)利用链表和hashmap。当需要插入新的数据项的时候,如果新数据项在链表中存在(一般称为命中),则把该节点移到链表头部;如果不存在,则新建一个节点,放到链表头部。若缓存满了,则把链表最后一个节点删除即可。在访问数据的时候,如果数据项在链表中存在,则把该节点移到链表头部,否则返回-1。这样一来在链表尾部的节点就是最近最久未访问的数据项。

在已知要删除的节点的情况下,如何在O(1)时间复杂度内删除节点?

假如要删除的节点是cur,通过cur可以知道cur节点的后继节点curNext,如果交换cur节点和curNext节点的数据域,然后删除curNext节点(curNext节点是很好删除地),此时便在O(1)时间复杂度内完成了cur节点的删除。

如何使得删除末尾节点的复杂度也在O(1)?

利用双向链表,并提供head指针和tail指针,这样一来,所有的操作都是O(1)时间复杂度。

参考

[1] https://www.cnblogs.com/argenbarbie/p/5401133.html

设计一个虚拟存储区和内存工作区,并使用下列算法计算访问命中率. (1) 进先出的算法(FIFO) (2) 最近最少使用的算法(LRU) (3) 最佳淘汰算法(OPT)(4) 最少访问页面算法(LFU) (5) 最近最不经常使用算法(NUR) 命中率=1-页面失效次数/页地址流长度 本实验的程序设计基本上按照实验内容进行。即首先用 srand()和 rand()函数定 义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法 计算出相应的命中率。相关定义如下: 1 数据结构 (1)页面类型 typedef struct{ int pn,pfn,counter,time; }pl-type; 其中 pn 为页号,pfn 为面号, counter 为一个周期内访问该页面的次数, time 为访问时间. (2) 页面控制结构 pfc-struct{ int pn,pfn; struct pfc_struct *next;} typedef struct pfc_struct pfc_type; pfc_type pfc_struct[total_vp],*freepf_head,*busypf_head; pfc_type *busypf_tail; 其中 pfc[total_vp]定义用户进程虚页控制结构, *freepf_head 为空页面头的指针, *busypf_head 为忙页面头的指针, *busypf_tail 为忙页面尾的指针. 2.函数定义 (1)Void initialize( ):初始化函数,给每个相关的页面赋值. (2)Void FIFO( ):计算使用 FIFO 算法时的命中率. (3)Void LRU( ):计算使用 LRU 算法时的命中率. (4)Void OPT( ):计算使用 OPT 算法时的命中率. (5)Void LFU( ):计算使用 LFU 算法时的命中率. (6)Void NUR( ):计算使用 NUR 算法时的命中率. 3.变量定义 (1)int a[total_instruction]: 指令流数据组.(2)int page[total_instruction]: 每条指令所属的页号. (3)int offset[total_instruction]: 每页装入 10 条指令后取模运算页号偏移 值. (4)int total_pf: 用户进程的内存页面数. (5)int disaffect: 页面失效次数.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值