Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

LRU是虚拟内存技术中,页置换时需要用到的算法,最近最少使用算法。也就是说替换掉最近最少被使用的页。

采用双链表实现一个栈,栈顶(用head指针表示)放最近使用的元素。end指针表示栈底,地方不够的时候end指针的元素值就会被覆盖,覆盖后因为成了最近使用,所以会被提到head的位置。链表中部也可能有元素被提到head的位置。

class LRUCache{
struct ListNode{
int key;
int value;
ListNode* prev;
ListNode* next;
};
public:
LRUCache(int capacity){
if(capacity >= ){
Capacity = capacity;
size = ;
}
} void set(int key, int value){
ListNode* p = head;
for(; p != NULL && p -> key != key; p = p -> next);
if(p == NULL && size == Capacity){ //The case that didn't find key and capacity is full
p = end;
p -> key = key;
}
if(p != NULL){ //The case that has found the key (treat the previous case as found the key in end)
p -> value = value;
if(p != head){ //If the key is in head of the list, we don't need to do anything since the head is the most recently used.
ListNode* pre = p -> prev;
ListNode* fol = p -> next; if(p == end && pre != NULL){
end = pre;
}
p -> next = head;
p -> prev = NULL;
head -> prev = p;
head = p; if(pre != NULL)
pre -> next = fol;
if(fol != NULL)
fol -> prev = pre;
}
}else{ //The case that has not found the key, and capacity is not full, need to create one.
p = new ListNode();
p -> key = key;
p -> value = value;
if(head == NULL){
head = end = p;
p -> prev = NULL;
p -> next = NULL;
}else{
p -> prev = NULL;
p -> next = head;
head -> prev = p;
head = p;
}
size++;
} } int get(int key){
ListNode* p = head;
for(; p != NULL && p -> key != key; p = p -> next);
if(p == NULL) return -; if(p != head){
ListNode* pre = p -> prev;
ListNode* fol = p -> next;
if(p == end)
end = pre; p -> next = head;
p -> prev = NULL;
head -> prev = p;
head = p; if(pre != NULL)
pre -> next = fol;
if(fol != NULL)
fol -> prev = pre;
}
return p -> value;
}
private:
ListNode* head = NULL;
ListNode* end = NULL;
int size = ;
int Capacity = ;
};

[Leetcode] LRU 算法实现的更多相关文章

  1. LRU算法的设计

    一道LeetCode OJ上的题目,要求设计一个LRU(Least Recently Used)算法,题目描述如下: Design and implement a data structure for ...

  2. Leetcode:LRU Cache,LFU Cache

    在Leetcode上遇到了两个有趣的题目,分别是利用LRU和LFU算法实现两个缓存.缓存支持和字典一样的get和put操作,且要求两个操作的时间复杂度均为O(1). 首先说一下如何在O(1)时间复杂度 ...

  3. LRU算法 - LRU Cache

    这个是比较经典的LRU(Least recently used,最近最少使用)算法,算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”. 一般应 ...

  4. LRU算法原理解析

    LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法,是为虚拟页式存储管理服务的. 现代操作系统提供了一种对主存的抽象概念虚拟内存,来对主存进行更好地管理.他将主存 ...

  5. 如何实现LRU算法?

    1.什么是LRU算法? LRU是一种缓存淘汰机制策略. 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新的内容腾位置.但是要删除哪些内容呢?我们肯定希望删掉那些没有用的缓存,而把有用的数据继续 ...

  6. 动手实现 LRU 算法,以及 Caffeine 和 Redis 中的缓存淘汰策略

    我是风筝,公众号「古时的风筝」. 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. 那天我在 LeetCode 上刷到一道 LRU 缓存机制的问题, ...

  7. Redis 为何使用近似 LRU 算法淘汰数据,而不是真实 LRU?

    在<Redis 数据缓存满了怎么办?>我们知道 Redis 缓存满了之后能通过淘汰策略删除数据腾出空间给新数据. 淘汰策略如下所示: 设置过期时间的 key volatile-ttl.vo ...

  8. Android图片缓存之Lru算法

    前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...

  9. 缓存淘汰算法--LRU算法

    1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...

随机推荐

  1. [问题] docker: Failed to start Docker Application Container Engine.

    docker无法启动: # systemctl restart docker Job for docker.service failed because the control process exi ...

  2. leetcode个人题解——#5 Container with most water

    class Solution { public: string longestPalindrome(string s) { int length = s.length(); ) return s; ; ...

  3. Java静态方法,静态变量,初始化顺序

    1. 静态方法: 成员变量分为实例变量和静态变量.其中实例变量属于某一个具体的实例,必须在类实例化后才真正存在,不同的对象拥有不同的实例变量.而静态变量被该类所有的对象公有(相当于全局变量),不需要实 ...

  4. BZOJ 4557 JLOI2016 侦查守卫 树形dp

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4557 题意概述: 给出一棵树,每个点付出代价w[i]可以控制距离和它不超过d的点,现在给 ...

  5. for和foreach的一点总结

    两者都是数组的循环遍历,但是区别还是有点: for循环,如果块内有事件操作,那么i是不会等事件操作时候在依次增加,而是一次性走完,,也就是依靠下标定位,下标已经走完了,而foreah是依次增加,它是依 ...

  6. JavaScript初探系列之String的基本操作

    1.字符串转换 字符串转换是最基础的要求和工作,你可以将任何类型的数据都转换为字符串,你可以用下面三种方法的任何一种: var myStr = num.toString(); // "19& ...

  7. 3dContactPointAnnotationTool开发日志(七)

      调了半天发现是逻辑错误,改了一下终于没那么奇怪了:   但是有的接触点很明显跑偏了.再回顾一下自己是怎么求的,我是直接用的下面的代码求解一个点是否在另一个物体内部: var bounds = us ...

  8. SVM之对偶问题

    SVM之问题形式化 >>>SVM之对偶问题 SVM之核函数 SVM之解决线性不可分 写在SVM之前——凸优化与对偶问题 前一篇SVM之问题形式化中将最大间隔分类器形式化为以下优化问题 ...

  9. Matlab快捷键

    1. 在命令窗口(Command Window)中: 1) [上.下键]――切换到之前.之后的命令,可以重复按多次来达到你想要的命令 2) clc――清除命令窗口显示的语句,此命令并不清空当前工作区的 ...

  10. TCP协议详解7层和4层解析(美团,阿里) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌握

    如果想了解HTTP的协议结构,原理,post,get的区别(阿里面试题目),请参考:HTTP协议 结构,get post 区别(阿里面试) 这里有个大白话的解说,可以参考:TCP/IP协议三次握手和四 ...