FIFO算法,LRU算法,OPT算法,LFU算法的C++实现
#include <bits/stdc++.h> using namespace std; /** * FIFO算法的实现:其实是可以采用双端队列,然后限制一下 * 双端队列的长度,根据我的限制应该是4。对于查询是否出现 * 在这个队列里面,我们可以采用一个数组标记是否有存在。 * * 测试数据如下 16 4 0 1 2 4 3 4 5 1 2 5 1 2 3 4 5 6 * **/ struct FIFO{ int len, m;///长度, len - 总访问数; m - 分配的物理块数 int arr[105];///存储访问页面的编号 deque<int>que; int vids[15];///标记数组,标记在当前可以查找到的序号 double result; int a;///a - 非缺页数 void Print(deque<int>a){ while(!a.empty()){ printf("%d ", a.front()); a.pop_front(); } printf("\n"); } void Init(){///初始化函数 while(!que.empty()){ que.pop_back(); } memset(vids, 0, sizeof(vids)); } void solve(){ scanf("%d%d", &len, &m);///输入处理的数字的长度,输入有多少可用物理块 for(int i = 0; i < len; i ++){ scanf("%d", &arr[i]);///预先输入处理的数据 } int r = 0;///从第一个数据开始判断 while(r < len){///如果没有到达尾部,接着运行 if(!vids[arr[r]]){///如果不在物理块中 a ++;///非缺页数加一 printf("*: "); if(que.size() < m){///物理块的储存的内容小于m que.push_back(arr[r]);///则将序号放入双端队列 } else{///数量超过了,要实现的是弹出队头,然后把在队列中的标记去掉 int nums = que.front();///获取队头元素 que.pop_front();///弹出队头 vids[nums] --;///把出现过的标志去掉 que.push_back(arr[r]);///队列压入新的元素 } vids[arr[r]] ++;///把对应的元素的值++ } Print(que); r ++;///移动到下一个元素 } printf("Number of page breaks = %d Total number of visits = %d\n", a, len); result = double(a) / double(len); printf("f = %f\n", result); } }f; int main(){ f.Init(); f.solve(); }
#include <bits/stdc++.h> using namespace std; /** * LRU算法的实现:可以使用一个结构体,来储存对应的数据 * 那么使用一个vector动态数组来储存当前的物理块中的内容 * 那么每访问一次就更新结构体中的value值,那么对vector数组 * 进行对应sort排序,即按照value从大到小排序,然后每次弹出队尾 * 将最小的value值的结构体弹出 * 测试数据如下 16 4 0 1 2 4 3 4 5 1 2 5 1 2 3 4 5 6 * **/ struct LRU_node{///LRU的节点结构 int key, value;///key代表节点最后一次出现的序号,value代表节点的权值 }; bool cmp(const LRU_node &a, const LRU_node &b){ return a.key > b.key;///排序,自定义排序cmp方法 } struct LRU{ int arr[105];///arr即存储当前的数据 vector<LRU_node>vec;///动态数组储存节点 int vids[105];///标记数组 void Init(){///清空函数 memset(vids, 0, sizeof(vids)); memset(arr, 0, sizeof(arr)); vec.clear(); } void slove(){ int n, m; scanf("%d%d", &n, &m);///n 代表输入的序列的长度是多少, m代表物理块的大小 for(int i = 0; i < n; i ++){ scanf("%d", &arr[i]); } int flag = 0;///缺页数 int r = 0;///遍历边界 while(r < n){ LRU_node a; a.key = r; a.value = arr[r];///获取一个节点 if(!vids[a.value]){///物理块中没有这个数 flag ++;///缺页数加一 printf("*: ");///代表缺页 if(vec.size() < m){///vec的数量小于物理块m vec.push_back(a); vids[a.value] ++;///标记块中出现的数 sort(vec.begin(), vec.end(), cmp);///排序,保证弹出的肯定是时间最开始的那个 } else{///vec的数量等于物理块的大小 sort(vec.begin(), vec.end(), cmp);///排序 LRU_node en = vec[vec.size() - 1];///取出最后的那个即时间最开始的那个 vids[en.value] --;///把弹出的数去掉 vec.pop_back(); vec.push_back(a);///把新的值压入vec vids[a.value] ++;///标记新的值在块中出现 sort(vec.begin(), vec.end(), cmp);///排序 } for(int i = 0; i < vec.size(); i ++){ printf("%d ", vec[i].value); } printf("\n"); } else{///否则在块中有对应的数 for(int i = 0; i < vec.size(); i ++){///遍历块中数据 if(vec[i].value == a.value){ vec[i].key = a.key;///更新块中的数据所对应的key值,即出现的最后的时间 break; } } sort(vec.begin(), vec.end(), cmp);///排序 for(int i = 0; i < vec.size(); i ++){ printf("%d ", vec[i].value); } printf("\n"); } r ++; } printf("Number of page breaks = %d Total number of visits = %d\n", flag, n); printf("f = %lf\n", double(flag) / double(n)); } }l; int main(){ l.Init(); l.slove(); return 0; }
#include <bits/stdc++.h> /** * 思路:采用队列来保存每个每个值对应的下一个出现的位置 * 如果只后都不出现,那就把这个值置为无穷大,那么这样的 * 话就能保证这个值,会被先弹出动态数组,那么就能保证实 * 现对应的按照最远出现的位置来淘汰对应的数字。 * **/ using namespace std; const int MAXN = 105;///可以控制出现的编号的范围,我假设只会出现105以内的数字 const int inf = 0x7fffffff;///int 的最大值,代表这个数再也不会出现 int n, m;///n 代表序列的长度, m代表物理块的大小 queue<int>que[MAXN];///记录下一个该数字出现的位置 int arr[MAXN];///储存序列 int vids[MAXN];///标记块中是否存在这个 bool cmp(const int &a, const int &b){ return que[a].front() < que[b].front();///按照下一次出现的位置从小到大排序 ///保证可以将最远访问的块进行更换 } struct opt{ void Init(){///清空 for(int i = 0; i < MAXN; i ++){///清空队列 while(!que[i].empty()){ que[i].pop(); } } memset(vids, 0, sizeof(vids));///清空标记数组 memset(arr, 0, sizeof(arr));///清空数组 return ; } void solve(){ int f = 0;///缺页数 scanf("%d%d", &n, &m); Init(); for(int i = 0; i < n; i ++){ scanf("%d", &arr[i]); que[arr[i]].push(i);///将对应的出现的位置放入队列中 } for(int i = 0; i < MAXN; i ++){ que[i].push(inf);///全部放入完成后,放入一个无穷大 ///这样的好处是如果这个数,后面不再出现,就视为无穷大 } int r = 0; vector<int>vec;///物理块使用动态数组模拟 vec.clear(); while(r < n){ if(!vids[arr[r]]){///如果在物理块中没有出现 f ++;///对应的缺页数加一 printf("*: ");///代表缺页 if(vec.size() < m){///如果没有达到物理块上限 vec.push_back(arr[r]);///动态数组压入对应的物理块 vids[arr[r]] ++;///标记物理块存在出现 que[arr[r]].pop();///把对应的位置弹出,使其更新为下一个最近的位置 } else{ sort(vec.begin(), vec.end(), cmp);///否则达到上限,按照后面出现的位置排序 int temp = vec[vec.size() - 1];///获取队尾的数值 vids[temp] --;///把对应的数值的出现标记抹去 vec.pop_back();///将队尾弹出 vec.push_back(arr[r]);///压入新的数值 vids[arr[r]] ++;///把对应的数值的出现标记更新 que[arr[r]].pop();///把对应新的数值的下一个出现的位置进行更新 } /**输出物理块中的内容**/ for(int i = 0; i < vec.size(); i ++){ printf("%d ", vec[i]); } printf("\n"); } else{ que[arr[r]].pop();///在物理块中,将对应的值的后续的出现位置进行更新 sort(vec.begin(), vec.end(), cmp);///按照出现的位置的远近排序 for(int i = 0; i < vec.size(); i ++){///输出块中的内容 printf("%d ", vec[i]); } printf("\n"); } r ++; } printf("Number of page breaks = %d Total number of visits = %d\n", f, n); printf("%f\n", double(f) / double(n)); } }a; /** 测试样例如下: 12 3 2 3 2 1 5 2 4 5 3 2 5 2 **/ int main(){ a.solve(); return 0; }
#include <bits/stdc++.h> using namespace std; /** * 思路:lfu的实现,可以使用Map<int, int>来实现计数 * 或者使用int数组来标记出现的次数,然后每次进行对次数 * 的排序就行了,然后每次淘汰访问次数最小的就ok了,如果 * 数据范围较小的话,使用int数组来标记的话,把每次查询的 * 复杂度降到O(1),所以下面的代码实现使用数组来标记出现的 * 次数 * **/ const int MAXN = 105; int flag[MAXN]; ///下标代表出现的数值,下标里的数值代表被访问的次数 bool cmp(const int &a, const int &b) { ///按照被访问的次数进行从大到小的排序 return flag[a] > flag[b]; ///这样能保证更换物理块的时候是按照出现的次数最小的被更换 } struct LFU { vector<int> vec;///代表物理块 int vids[MAXN];///代表物理块中出现的数 int n, m; void Init()///初始化函数 { vec.clear(); memset(vids, 0, sizeof(vids)); memset(flag, 0, sizeof(flag)); } void solve() { int f = 0;///缺页数 scanf("%d%d", &n, &m); Init(); for (int i = 0; i < n; i++) { int num; scanf("%d", &num);///输入一个值 if (!vids[num])///判断是否在物理块中 { f ++; printf("*: "); if (vec.size() < m)///如果数量小于物理块的数量 { vec.push_back(num);///直接压入物理块 vids[num]++;///标记其出现 flag[num]++;///对应的出现次数加一 } else { sort(vec.begin(), vec.end(), cmp);///针对出现的次数排序 int temp = vec[vec.size() - 1];///获取出现次数最小的数的值 vids[temp]--;///将其标记去掉 flag[temp] = 0;///将其访问的次数变为0 vec.pop_back();///将其弹出队列 vec.push_back(num);///将新的值压入内存块 vids[num]++;///将新的值标记出现 flag[num]++;///将新的值得出现次数加一 } sort(vec.begin(), vec.end(), cmp);///排序 for (int i = 0; i < vec.size(); i++)///输出物理块 { printf("%d ", vec[i]); } printf("\n"); } else { flag[num]++;///在物理块中,将访问值加一 sort(vec.begin(), vec.end(), cmp);///排序 for (int i = 0; i < vec.size(); i++)///输出物理块的情况 { printf("%d ", vec[i]); } printf("\n"); } } printf("Number of page breaks = %d Total number of visits = %d\n", f, n); printf("%f\n", double(f) / double(n)); } } a; int main() { a.solve(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用