实现语言:go lang
LRU
最近最少未使用,是一种淘汰策略,当缓存空间不够使用的时候,淘汰一个最久没有访问的存储单元。目前已知较好表现的替换策略,具体原因翻教材。
题目要求:编写一个LRU具体类,完成指定方法,Get(key int) int {} 与 Set(key int, value int) {}
并且需要保证两个方法的时间复杂度都需要在O1
既然是是缓存而且是替换策略,我们就先假设放在一个数组里面。
最主要需要考虑替换策略。所以我们假定数组已经满了,这时候我需要set一个新的键值对进来,我需要替换哪一个?
这时候就感觉好像似乎需要针对访问顺序产生优先级顺序。但这个优先级顺序不能用排序解决,因为无论哪种排序都不可能在O1完成。
每一次最久没有访问的其实可以认为是一个贪心选择。那么假设每一次访问之后,都把访问结点往前放,那么到淘汰时候一定是末尾的淘汰。
确定出方法,就需要确定数据结构以满足时间复杂度的限制。
显然之前假定的数组不可行。因为按照刚才的思路,访问的时候都需要改变一下顺序,数组显然不好改变顺序。
但链表可以,既好改变顺序,同时也好删除,复杂度都是O1.
确定了数据结构,能够解决顺序与删除问题,就剩下最后一个问题,查找。
无论是Get还是进行删除之前都需要进行查找,而且也需要保证复杂度O1。
显然就只剩下hash了。
所以可以确定下来所用的数据结构为链表与hashtable
省下的就是go语言编码的问题了
go container/list
container/list是直接使用双向链表的,没有但链表这个选项,直接用就可以。
内部数据结构分为Element与List
Element相当于自己写链表的Node,内部含有结点值,前后结点的指针。
List是相当于进行封装,里面全是一堆方法。
比较有用的就是
- 直接含有size计数
- Front/Back方法,返回头/尾 Element
- move方法,移动结点到首部/尾部/随便结点后面
- delete方法,删除某个节点
具体哪个方法,查阅一下文档
https://pkg.go.dev/container/list#pkg-functions
方法不详述,直接翻官方文档就好了。
import "container/list"
func main() {
// 构造一个list对象,前面这个list代表list这个package
l := list