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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM