数据结构-链表

361 阅读2分钟

链表

单链表

  • 结构:-->data|next-->data|next-->null
  • 你应该可以发现,其中有两个结点是比较特殊的,它们分别是第一个结点和最后一个结点。我们习惯性地把第一个结点叫作头结点,把最 后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了它,我们就可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而 是指向一个空地址NULL,表示这是链表上最后一个结点

循环链表

  • 循环链表的尾节点指针是指向链表的头结点。
  • image.png

循环链表的优点是从链尾到链头比较方便。当要处理的数据具有环型结构特点时,就特别适合采用循环链表。比如著名的约瑟夫问题。尽管用单 链表也可以实现,但是用循环链表实现的话,代码就会简洁很多

双向链表

  • 需要额外的两个空间来存储后继及诶单和前驱节点的地址,比单链占用更多内存,但可以支持双向遍历
  • image.png
  • 对于删除节点中"值等于某个给定值"的结点,两种方式都差不多
  • 对于删除给定指针指向的结点,由于双向链表记录了前驱结点的指针,不需要像单链表一样遍历
  • 查询效率也比一般的链表快,平均只需要查找一半的数据
  • JAVA中的LinkedHashMap

双向循环链表

  • image.png

基于链表实现LRU缓存淘汰算法

  • 维护一格有序单链表,越靠近尾部数据越早。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。

  • 1.如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。

  • 2.如果此数据没有在缓存链表中,又可以分为两种情况:

如果此时缓存未满,则将此结点直接插入到链表的头部;    如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。

  • 优化:引入散列表来记录每个数据的位置。

基于数组实现LRU缓存淘汰策略

  • 方式一:首位置保存最新访问数据,末尾位置优先清理
  • 方式二:首位置优先清理,末尾位置保存最新访问数据(优化:清理的时候可以考虑一次性清理一定数量,减少清理次数)