请你讲讲LRU算法的实现原理?
- LRU算法:LRU算法用于缓存淘汰。思路是将缓存中最近最少使用的对象删除掉
- 实现方式:利用链表和hashmap。 当需要插入新的数据项的时候,如果新数据项在链表中存在(一般称为命中),则把该节点移到链 表头部,如果不存在,则新建一个节点,放到链表头部,若缓存满了,则把链表最后一个节点删除 即可。 在访问数据的时候,如果数据项在链表中存在,则把该节点移到链表头部,否则返回-1。这样一来 在链表尾部的节点就是最近最久未访问的数据项。
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;//否则返回-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();//将键映射到链表头部 } }; /** * Your LRUCache object will be instantiated and called as such: * LRUCache* obj = new LRUCache(capacity); * int param_1 = obj->get(key); * obj->put(key,value); */
该代码实现了一个LRU Cache,使用双向链表和哈希表来存储缓存的键值对,并使用LRU(Least Recently Used)算法来淘汰最久未使用的键值对。通过双向链表来维护缓存的顺序,从而实现快速的插入、删除和移动操作;同时,通过哈希表来实现快速的查找操作,从而实现O(1)的时间复杂度。