• 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("
    ");
        }
        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
    ", a, len);
            result = double(a) / double(len);
            printf("f = %f
    ", 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("
    ");
                }
                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("
    ");
                }
                r ++;
            }
            printf("Number of page breaks = %d Total number of visits = %d
    ", flag, n);
            printf("f = %lf
    ", 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("
    ");
                }
                else{
                    que[arr[r]].pop();///在物理块中,将对应的值的后续的出现位置进行更新
                    sort(vec.begin(), vec.end(), cmp);///按照出现的位置的远近排序
                    for(int i = 0; i < vec.size(); i ++){///输出块中的内容
                        printf("%d ", vec[i]);
                    }
                    printf("
    ");
                }
                r ++;
            }
            printf("Number of page breaks = %d Total number of visits = %d
    ", f, n);
            printf("%f
    ", 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("
    ");
                }
                else
                {
                    flag[num]++;///在物理块中,将访问值加一
                    sort(vec.begin(), vec.end(), cmp);///排序
                    for (int i = 0; i < vec.size(); i++)///输出物理块的情况
                    {
                        printf("%d ", vec[i]);
                    }
                    printf("
    ");
                }
            }
            printf("Number of page breaks = %d Total number of visits = %d
    ", f, n);
            printf("%f
    ", double(f) / double(n));
        }
    } a;
    int main()
    {
        a.solve();
        return 0;
    }
  • 相关阅读:
    打印机共享为什么老是出现“操作无法完成(错误 0X00000709)。再次检查打印机名称、并确保打印机连接网络
    给UITextField设置头或尾空白
    Objective-C中的关联(objc_setAssociatedObject,objc_getAssociatedObject,objc_removeAssociatedObjects)
    定时器在多线程中的使用
    block知识点
    UIViewController新方法的使用(transitionFromViewController:toViewController:duration:options:animations:completion:)
    NSMutableAttributedString 的使用方法,设置格式
    statusbar的颜色设置
    获取图片的缩略图
    彻底理解position与anchorPoint
  • 原文地址:https://www.cnblogs.com/qq136155330/p/10817299.html
Copyright © 2020-2023  润新知