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),以空间换时间。

 

posted @ 2018-07-13 16:32  Hwangzhiyoung  阅读(3506)  评论(0编辑  收藏  举报