FIFO:先进先出策略,实现简单,但很多场景下,部分记录虽然是最早添加但也最常被访问,这类数据会被频繁添加、淘汰,导致缓存命中率较低。
LFU:淘汰最少使用,命中率较高,但维护每个记录的访问次数,对内存的消耗较高。
LRU作为缓存淘汰算法,相对于仅考虑时间因素的FIFO和仅考虑访问频率的LFU,LRU算法可以认为是相对平衡的一种淘汰算法。
LRU算法的实现非常简单,维护一个队列,如果某条记录被访问了,则移动到队尾,那么队首是最近最少访问的数据,淘汰该条记录即可。

- 绿色的是字典,存储键和值的映射关系。这样根据某个键(key)查找对应的值(value)的复杂是
O(1)
,在字典中插入一条记录的复杂度也是O(1)
。
- 红色的是双向链表实现的队列。将所有的值放到双向链表中,这样,当访问到某个值时,将其移动到队尾的复杂度是
O(1)
,在队尾新增一条记录以及删除一条记录的复杂度均为O(1)
。
Leetcode - LRU缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| struct DLinkedNode { int key, value; DLinkedNode* prev; DLinkedNode* next; DLinkedNode() : key(0), value(0), prev(nullptr), next(nullptr) {} DLinkedNode(int _key, int _value) : key(_key), value(_value), prev(nullptr), next(nullptr) {} };
class LRUCache { unordered_map<int, DLinkedNode*> cache; DLinkedNode* head; DLinkedNode* tail; int size; int capacity; public: LRUCache(int _capacity): capacity(_capacity), size(0) { head = new DLinkedNode(); tail = new DLinkedNode(); head->next = tail; tail->prev = head; }
int get(int key) { if (!cache.count(key)) { return -1; } DLinkedNode* node = cache[key]; moveToHead(node); return node->value; }
void put(int key, int value) { if (!cache.count(key)) { DLinkedNode* node = new DLinkedNode(key, value); cache[key] = node; addToHead(node); ++size; if (size > capacity) { DLinkedNode* removed = removeTail(); cache.erase(removed->key); delete removed; --size; } } else { DLinkedNode* node = cache[key]; node->value = value; moveToHead(node); } }
void addToHead(DLinkedNode* node) { node->prev = head; node->next = head->next; head->next->prev = node; head->next = node; }
void removeNode(DLinkedNode* node) { node->prev->next = node->next; node->next->prev = node->prev; }
void moveToHead(DLinkedNode* node) { removeNode(node); addToHead(node); }
DLinkedNode* removeTail() { DLinkedNode* node = tail->prev; removeNode(node); return node; } };
|