2020-12-27 LRU算法原理

本文主要介绍一下LRU算法,least recently used,
翻译中文就是,最常使用的放在最优先级的位置,也就是按照使用的次序从近到远排序;

下面举例来说;

有 1,2,3,4,5个对象;我先使用了2,再使用了1,最后使用了3;
则顺序为: 3,1,2,4,5
这是因为最近使用的是3,其次是1,其次是2;

然后可以新加入对象,比如加入6(加入也视为一次使用),则顺序变为:
6,3,1,2,4,5

还有个需求,就是可保留的对象个数有限,比如最多就6个;
当再加入新对象时,要把最不常使用的删除;

比如加入7,则5是最不常使用的;删除,变为:
7,6,3,1,2,4

LRU是一个数据结构,主要支持两个函数
get(key), put(key,value)
含义很明显,一个是根据key,访问 值;还有一个是,把key设为对应值,要求是这两个函数都在O(1)时间完成;
类似一个map的功能,不过它有个额外能力,就是容量受限,可以把最不常用的自动删除;(或者按照从最近使用到最久使用的顺序把数据列出来)

下面我们看如何实现该结构;
从上面可以猜测用链表实现,不过链表无法实现O(1)访问,
LRU实际就是一个 hashMap + 双向List;

List中的节点是
{
key
value
}

hashMap中的值是:
{
key
ListNode*
}

也就是hashMap维护着key到链表节点的映射;

当需要访问的时候,直接通过hashMap的key O(1)索引到链表指针,进而取到value;
同时把访问的节点移动到链表首部是容易的;

下面画个图来说明:
还是用上面的例子来讲解,这里为简化假设链表中的key,value都相等,链表中就只写key了
初始:
list : n1{1} <->n2(2) <->n3{3}<->n4{4}<-> n5{5}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (5,n5)

先使用了2:
则通过hash_map获取到 n2节点,O(1);
再通过n2得到value 2 O(1);
再把n2移动到链表首部,O(1),(因为是双向链表,很容易把该节点O(1)时间移动到首部)
整体时间为O(1),
变为:
list : n2{2} <->n1(1) <->n3{3}<->n4{4}<-> n5{5}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (5,n5)

类似的使用了1,之后:
list : n1{1} <->n2(2) <->n3{3}<->n4{4}<-> n5{5}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (5,n5)

使用了3之后:
list : n3{3} <->n1(1) <->n2{2}<->n4{4}<-> n5{5}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (5,n5)

可见使用元素不改变hashMap,只改变链表;

之后加入key=6:
相当于在hashMap里插入一个元素,时间O(1),同时在链表首部插入元素也是O(1),变为,
list : n6{6}<->n3{3} <->n1(1) <->n2{2}<->n4{4}<-> n5{5}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (5,n5) (6,n6)

之后加入key=7:
此时可以把链表尾部元素删除;同时更新map,变为:
list : n7{7}<->n6{6}<->n3{3} <->n1(1) <->n2{2}<->n4{4}
hash_map: (1,n1) (2,n2) (3,n3) (4,n4) (6,n6)(7,n7)

此时链表尾部访问速度为O(1),删除速度是O(1),hash_map删除也是O(1);

综上,就实现了LRU数据结构算法,
可见,总结一下,
LRU其实就是用hashMap的O(1)访问能力弥补了链表的访问不足;
又利用了链表的可以很方便的把某个节点移动到首部,以及有序性的特性 弥补了hashMap的顺序性缺失,
从而者结合达到预定效果;

至此LRU算法原理就以一种非常浅显易懂的方式介绍玩了,,如果觉着好,可以点个赞,加个糖果,你的支持是我继续创作的动力

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容