链表的应用(进阶)——LRU 缓存
设计和构建一个“最近最少使用”缓存,该缓存会删除最近最少使用的项目。缓存应该从键映射到值(允许你插入和检索特定键对应的值),并在初始化时指定最大容量。当缓存被填满时,它应该删除最近最少使用的项目。
它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。
基本的思路是,我们设计一个双向链表,一旦一个节点被访问,我们就把它挪动到链表的表头,也就是说,越往表头,这个节点越经常被访问,如果最少被访问,那么这个节点肯定在表尾。为了提高链表的查找效率,我们可以将链表对象同时用map做存储,克服链表查找效率低下的问题,同时也发挥了链表插入、删除效率高的特性。
我们首先可以设计一个结构体,用于存储缓存节点:
这里第一个了一个方法用于删除当前节点。
接着,我们设计 LRU 结构体:
这里的 setHeader 方法用于将当前节点放入链表表头。
这里的创建函数需要注意下,我们创建了一个带表头和表尾的双向链表,表头和表尾不存储元素,只是方便操作。
我们继续设计 LRU 的 Get 方法:
如果查找到,就先将n从链表中当前位置移除并挪动到表头。
最后,我们设计 LRU 的 Put 方法:
这里的做法比较巧妙,如果查找到 key 值在链表中已经存在,我们的处理方式是先将其从表中移除,且从map 中移除(防止出现 key 值重复)。接着如果容量已满,则删除表尾元素,将新节点创建并放入表头。
最后更新于