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

 

转载于:https://www.cnblogs.com/Hwangzhiyoung/p/9305786.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LRU算法(最近最少使用算法)是一种用于缓存淘汰的算法。其原理是根据数据的访问时间来确定是否将其从缓存中删除。当缓存达到最大容量时,如果要插入新数据,则需要将最近最少使用的数据删除,以腾出空间。 以下是C++实现LRU算法的基本思路: 1. 使用一个双向链表来维护缓存的数据。 2. 使用一个哈希表来快速查找数据是否在缓存中。 3. 当一个数据被访问时,将其移动到链表头部。 4. 当需要插入新数据时,先检查缓存是否已满,如果已满,则删除链表尾部的数据,并将新数据插入到链表头部。 5. 当需要删除数据时,直接从链表中删除即可。 以下是C++代码示例: ``` #include <iostream> #include <unordered_map> using namespace std; class LRUCache { private: struct Node { int key; int value; Node* prev; Node* next; Node(int k, int v) : key(k), value(v), prev(nullptr), next(nullptr) {} }; int capacity; unordered_map<int, Node*> map; Node* head; Node* tail; void addToHead(Node* node) { node->prev = nullptr; node->next = head; if (head) { head->prev = node; } else { tail = node; } head = node; } void removeNode(Node* node) { if (node == head) { head = node->next; } else if (node == tail) { tail = node->prev; } else { node->prev->next = node->next; node->next->prev = node->prev; } } public: LRUCache(int cap) : capacity(cap), head(nullptr), tail(nullptr) {} int get(int key) { if (map.find(key) != map.end()) { Node* node = map[key]; removeNode(node); addToHead(node); return node->value; } else { return -1; } } void put(int key, int value) { if (map.find(key) != map.end()) { Node* node = map[key]; node->value = value; removeNode(node); addToHead(node); } else { Node* newNode = new Node(key, value); if (map.size() == capacity) { map.erase(tail->key); removeNode(tail); delete tail; } map[key] = newNode; addToHead(newNode); } } }; int main() { LRUCache cache(2); cache.put(1, 1); cache.put(2, 2); cout << cache.get(1) << endl; // 输出 1 cache.put(3, 3); // 删除 key 2 cout << cache.get(2) << endl; // 输出 -1 cache.put(4, 4); // 删除 key 1 cout << cache.get(1) << endl; // 输出 -1 cout << cache.get(3) << endl; // 输出 3 cout << cache.get(4) << endl; // 输出 4 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值