链表
单链表
- 结构:-->data|next-->data|next-->null
- 你应该可以发现,其中有两个结点是比较特殊的,它们分别是第一个结点和最后一个结点。我们习惯性地把第一个结点叫作头结点,把最 后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了它,我们就可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而 是指向一个空地址NULL,表示这是链表上最后一个结点
循环链表
- 循环链表的尾节点指针是指向链表的头结点。
循环链表的优点是从链尾到链头比较方便。当要处理的数据具有环型结构特点时,就特别适合采用循环链表。比如著名的约瑟夫问题。尽管用单 链表也可以实现,但是用循环链表实现的话,代码就会简洁很多
双向链表
- 需要额外的两个空间来存储后继及诶单和前驱节点的地址,比单链占用更多内存,但可以支持双向遍历
- 对于删除节点中"值等于某个给定值"的结点,两种方式都差不多
- 对于删除给定指针指向的结点,由于双向链表记录了前驱结点的指针,不需要像单链表一样遍历
- 查询效率也比一般的链表快,平均只需要查找一半的数据
- JAVA中的LinkedHashMap
双向循环链表
基于链表实现LRU缓存淘汰算法
-
维护一格有序单链表,越靠近尾部数据越早。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。
-
1.如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
-
2.如果此数据没有在缓存链表中,又可以分为两种情况:
如果此时缓存未满,则将此结点直接插入到链表的头部; 如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。
- 优化:引入散列表来记录每个数据的位置。
基于数组实现LRU缓存淘汰策略
- 方式一:首位置保存最新访问数据,末尾位置优先清理
- 方式二:首位置优先清理,末尾位置保存最新访问数据(优化:清理的时候可以考虑一次性清理一定数量,减少清理次数)