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