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 |