链表
链表也是一种很常用的数据结构,可分为单向链表、循环链表、双向链表。
单向链表
链表节点中只有一个后继指针next,指向下一个节点。
只能从链表头部向链表尾部遍历。
循环链表
在单向链表的基础上增加了一个前驱指针prev,可以指向上一个节点。
链表的遍历方向可以从头部到尾部,也可以从尾部到头部。
双向链表
在循环链表的基础上,头节点的前驱指针prev指向尾节点,尾节点的后继指针next指向头节点。
链表的遍历方向可从头到尾的方向,也可从尾到头的方向,一直循环下去。
缓存的淘汰策略
缓存有三种淘汰策略:先进先出(FIFO)策略、最少使用(LFU)策略、最近最少(LRU)使用策略。
-
先进先出(FIFO)策略
先存入缓存的数据先被淘汰。 -
最少使用(LFU)策略
访问次数最少的数据先被淘汰。 -
最近最少(LRU)使用策略
最近最少被访问的数据先被淘汰,可使用双向链表结构来实现。
我们来研究下LRU策略的简单实现: 维护一个有序的双向链表,越靠近链表尾部的节点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。
- 如果此数据之前已经存在链表中,把这个数据所在节点移动到链表头部。
- 如果此数据不在链表中,分为如下两种情况:
- 如果此时缓存还有空间,把此节点插入到链表头部。
- 如果此时缓存已经满了,则删除链表尾部节点,把新数据插入到链表头部。
链表 VS 数组性能
时间复杂度 | 数组 | 链表 |
---|---|---|
插入和删除 | O(n) | O(1) |
随机访问 | O(1) | O(n) |
扩展
Redis中提供了多种缓存的淘汰策略,其中就包括:先进先出(FIFO)策略、最近最少(LRU)使用策略,感兴趣的同学可以去了解下:Using Redis as an LRU cache