面试题答案
一键面试选择的数据结构
- 双向链表(Doubly Linked List):用于实现LRU部分。链表节点存储缓存数据以及对应的访问频率等信息。双向链表方便在O(1)时间内进行节点的删除和移动操作。
- 哈希表(Hash Table):用于快速查找缓存项。哈希表的键为缓存数据的标识(如键值对中的键),值为双向链表中的节点指针,这样可以在O(1)时间内定位到链表中的对应节点,方便进行后续操作。
- 频率字典(Dictionary of Frequencies):记录每个访问频率对应的双向链表。每个频率对应一个双向链表,链表中节点为具有该访问频率的缓存数据。这有助于实现LFU部分,方便找到最不经常使用的数据。
实现思路
插入操作
- 检查缓存是否已满:如果缓存已满,根据LRU和LFU混合策略选择要淘汰的节点。
- 创建新节点:生成一个新的双向链表节点,包含要插入的数据、初始访问频率(通常设为1)等信息。
- 插入哈希表:将新节点的键值对插入哈希表,键为数据标识,值为新节点指针。
- 插入频率链表:将新节点插入到频率为1的双向链表头部。
查找操作
- 哈希表查找:通过哈希表快速查找是否存在目标缓存数据的节点指针。
- 若存在:
- 增加该节点的访问频率。
- 将节点从当前频率的双向链表中移除。
- 将节点插入到新频率对应的双向链表头部。
- 若新频率对应的双向链表为空,创建一个新的双向链表。
- 根据LRU策略调整双向链表顺序,将该节点移动到链表头部(表示最近使用)。
- 若不存在:返回未命中信息。
删除操作
- 哈希表查找:通过哈希表找到要删除的节点指针。
- 从双向链表移除:从当前所在的双向链表中移除该节点。
- 从哈希表删除:删除哈希表中对应的键值对。
- 调整频率链表:如果该节点所在频率的双向链表为空,从频率字典中删除该频率的链表。
平衡LRU和LFU权重
- 权重因子:引入一个权重因子(例如α,取值范围为[0, 1])来平衡LRU和LFU。α = 0时完全采用LFU策略,α = 1时完全采用LRU策略。
- 淘汰节点选择:当缓存已满需要淘汰节点时,先根据LFU策略从所有频率链表中找到最低频率的链表。如果最低频率链表中有多个节点,再根据LRU策略从这个链表中选择最久未使用的节点(链表尾部节点)。具体实现为在选择淘汰节点时,以α的概率从最久未使用的节点(按LRU)中选择,以1 - α的概率从访问频率最低的节点(按LFU)中选择。
通过以上数据结构和实现思路,可以有效地实现基于LRU和LFU混合的缓存替换策略。