LRU 缓存:请你设计并实现一个满足 LRU(Least Recently Used)缓存约束的数据结构。
实现 LRUCache
类:
LRUCache(int capacity)
以正整数作为容量 capacity
初始化 LRU 缓存。int get(int key)
如果关键字 key
存在于缓存中,则返回关键字的值,否则返回 -1
。void put(int key, int value)
如果关键字 key
已经存在,则变更其数据值 value
;如果不存在,则向缓存中插入该组 key-value
。如果插入操作导致关键字数量超过 capacity
,则应该逐出最久未使用的关键字。函数 get
和 put
必须以 O(1)
的平均时间复杂度运行。
1 | 输入 |
最近最久使用页面置换算法(Least Recently Used, LRU)是操作系统中局部页面置换算法中性能较好的一种算法,当一个缺页中断发生时,它选择 最近最久未使用 的那个页面淘汰。
在题目中,如果 get
方法获取的关键字存在于缓存中,除了要返回关键字对应的值,同时 这条记录将会被刷新为最近(最新)被使用的一条记录 。同样地,如果 put
方法存储的关键字存在于缓存中,除了要修改关键字对应的值,同时 这条记录也将会被刷新为最近(最新)被使用的一条记录。
题目还要求使用 O(1)
的平均时间复杂度完成 get
和 put
方法,这可以使用「双向链表」和「哈希表」来共同设计这个 LRU 缓存数据结构。
使用「双向链表」和「哈希表」来共同设计这个 LRU 缓存数据结构:
这样,我们在进行 get
操作时,可以使用关键字查找哈希表中的 key
,来获取它在双向链表中的地址:
-1
;在进行 put
操作时,可以使用关键字查找哈希表中的 key
,来获取它在双向链表中的地址:
双向链表:
1 | // 定义双向链表的结构体 |
哈希表:
1 | // 定义哈希表的结构体 |
LRU 缓存:
1 | // 定义 LRU 缓存的结构体 |
上述数据结构关系图:
创建 LRU 缓存:
1 | // 创建 LRU 缓存 |
实现 get
方法和 put
方法:
1 | void printDLinked(stDLinked *node) { |
针对上面的测试用例,给出了每步操作后的双向链表的内容,如下。
1 | Put: (1, 1) print DL: (1, 1)->NULL |