本文最后更新于:2022年4月9日 中午
实现 LRU 缓存数据结构。
参考:牛客 - 设计 LRU 缓存结构 、力扣 - 146 LRU 缓存机制
哈希表 + 双向链表
双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。
哈希表即为普通的哈希映射(HashMap),通过缓存数据的键映射到其在双向链表中的位置。
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 struct DListNode { int key, val; DListNode* pre; DListNode* next; DListNode(int k, int v) : key(k), val(v), pre(nullptr ), next(nullptr ) {} }; class Solution {private : int capacity = 0 ; int size = 0 ; DListNode* head; DListNode* tail; unordered_map <int , DListNode*> mp; public : int get (int key) { int ret = -1 ; if (mp.find(key) != mp.end()) { ret = mp[key]->val; moveToHead(mp[key]); } return ret; } void set (int key, int val) { if (mp.find(key) == mp.end()) { DListNode* node = new DListNode(key, val); mp[key] = node; addToHead(node); ++size; if (size > capacity) { DListNode* delNode = removeTail(); mp.erase(delNode->key); delete delNode; --size; } } else { DListNode* node = mp[key]; node->val = val; moveToHead(node); } } void addToHead (DListNode* node) { node->pre = head; node->next = head->next; head->next->pre = node; head->next = node; } void removeNode (DListNode* node) { node->pre->next = node->next; node->next->pre = node->pre; } void moveToHead (DListNode* node) { removeNode(node); addToHead(node); } DListNode* removeTail () { DListNode* node = tail->pre; removeNode(node); return node; } vector <int > LRU (vector <vector <int > >& operators, int k) { if (k < 1 ) return {}; this ->capacity = k; this ->head = new DListNode(0 ,0 ); this ->tail = new DListNode(0 ,0 ); this ->head->next = this ->tail; this ->tail->pre = this ->head; if (operators.size() == 0 ) return {}; vector <int > res; for (auto & op : operators) { if (op[0 ] == 1 ) { set (op[1 ], op[2 ]); } else if (op[0 ] == 2 ) { int value = get(op[1 ]); res.push_back(value); } } return res; } };
纯 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 class LRUCache { list <pair <int , int >> cache; unordered_map <int , list <pair <int , int >>::iterator> map ; int cap;public : LRUCache(int capacity) { cap = capacity; } int get (int key) { if (map .count(key) > 0 ){ auto temp = *map [key]; cache.erase(map [key]); map .erase(key); cache.push_front(temp); map [key] = cache.begin(); return temp.second; } return -1 ; } void put (int key, int value) { if (map .count(key) > 0 ){ cache.erase(map [key]); map .erase(key); } else if (cap == cache.size()){ auto temp = cache.back(); map .erase(temp.first); cache.pop_back(); } cache.push_front(pair <int , int >(key, value)); map [key] = cache.begin(); } };