LRU (近期最少使用)算法 c++實現


前言

這兩天碰到面試題,說是頁面調度算法,之前在操作系統書上有了解過,LRU(近期最少使用),還有OPT(最佳頁面替換算法)、FIFO(先進先出頁面置換算法),今天先來實現LRU 最近最少使用。

LRU 原理

LRU(Least recently used,最近最少使用)算法根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是“如果數據最近被訪問過,那么將來被訪問的幾率也更高”。

參照網上的寫法,給出以下例子做個參考:

 1 #include <iostream>
 2 #include <unordered_map>  
 3 #include <list>  
 4 #include <utility>  
 5 using namespace std;
 6 using namespace stdext;
 7 
 8 class LRUCache {
 9 public:
10     LRUCache(int capacity) {
11         m_capacity = capacity;
12     }
13 
14     int get(int key) {
15         int retValue = -1;
16         unordered_map<int, list<pair<int, int> > ::iterator> ::iterator it = cachesMap.find(key);
17 
18         //如果在Cashe中,將記錄移動到鏈表的最前端  
19         if (it != cachesMap.end())
20         {
21             retValue = it->second->second;
22             //移動到最前端  
23             list<pair<int, int> > ::iterator ptrPair = it->second;
24             pair<int, int> tmpPair = *ptrPair;
25             caches.erase(ptrPair++);
26             caches.push_front(tmpPair);
27 
28 
29             //修改map中的值  
30             cachesMap[key] = caches.begin();
31         }
32         return retValue;
33     }
34 
35     void set(int key, int value) {
36 
37         unordered_map<int, list<pair<int, int> > ::iterator> ::iterator it = cachesMap.find(key);
38 
39         if (it != cachesMap.end()) //已經存在其中  
40         {
41             list<pair<int, int> > ::iterator ptrPait = it->second;
42             ptrPait->second = value;
43             //移動到最前面  
44             pair<int, int > tmpPair = *ptrPait;
45             caches.erase(ptrPait);
46             caches.push_front(tmpPair);
47 
48 
49             //更新map  
50             cachesMap[key] = caches.begin();
51         }
52         else //不存在其中  
53         {
54             pair<int, int > tmpPair = make_pair(key, value);
55 
56 
57             if (m_capacity == caches.size()) //已經滿  
58             {
59                 int delKey = caches.back().first;
60                 caches.pop_back(); //刪除最后一個  
61 
62 
63                                    //刪除在map中的相應項  
64                 unordered_map<int, list<pair<int, int> > ::iterator> ::iterator delIt = cachesMap.find(delKey);
65                 cachesMap.erase(delIt++);
66             }
67 
68 
69             caches.push_front(tmpPair);
70             cachesMap[key] = caches.begin(); //更新map  
71         }
72     }
73 
74 
75 private:
76     int m_capacity;                                                                        //cashe的大小  
77     list<pair<int, int> > caches;                                                  //用一個雙鏈表存儲cashe的內容  
78     unordered_map< int, list<pair<int, int> > ::iterator> cachesMap;         //使用map加快查找的速度  
79 };
80 
81 
82 int main(int argc, char **argv)
83 {
84     LRUCache s(2);
85     s.set(2, 1);
86     s.set(1, 1);
87     cout << s.get(2) << endl;
88     s.set(4, 1);
89     s.set(5, 2);
90     cout << s.get(5) << endl;
91     cout << s.get(4) << endl;
92     getchar();
93     return 0;
94 }

在vs 2015 進行運行 ,輸出:

 

解釋:程序首先會初始化2個存儲空間的LRUCache類,依次插進{2, 1 },{1,1} ,之后輸出 key=2 => value=1 ,之后插進 {4, 1} , 因為已經滿了所以替換掉最近沒有使用的{1 ,1} ,變成了 { 4,1} ,{2,1} ,之后又插進{5, 2} ,又替換掉了 {2,1} ,變成了 {4, 1} ,{5,2},然后輸出剩下兩個key,再重新排序誰最近使用過。

用到的知識是 : 雙鏈表 + 哈希表 (使用map,內部元素自動排序;使用unordered_map內部不會進行有序排序)

頁面調度算法(LRU)的原理 :緩存機制中新數據或擊中的數據放到鏈表頭部,表示最近使用的數據,如果鏈表滿,從尾部淘汰數據。但只用鏈表會存在一個問題,擊中數據的時間復雜度為O(n),每次需要遍歷鏈表,所以引入哈希表,時間復雜度降到O(1),以空間換時間。

 


免責聲明!

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



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