链表基础总结

Posted xingrenguanxue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表基础总结相关的知识,希望对你有一定的参考价值。

技术图片

1. 简单介绍

链表,即线性表的链式存储结构,链表使用一组任意的存储单元来存储数据元素。如果某两个数据元素在逻辑位置上相邻,那么他们在物理位置上不一定相邻。如图:

技术图片

但是这样看着太乱了,为了看着舒服,表示方便,我们把这张图改成:

技术图片

2. 单向链表的结构和特点

在上图中,我们可以看出一个链表包含了存储的数据元素(方框中的值)以及这些数据元素之间逻辑关系(箭头,下一个数据元素的位置)。为了表示数据元素及逻辑关系,我们需要一个能存储它们的“载体”,这个载体就是结点(node)。它长这样:

技术图片

一个结点有两个部分:data是存储数据的数据域,next是存储它的下一个数据元素(在逻辑上)的位置信息的指针域

有了这两个部分,一个具体的单向链表如下:

技术图片

介绍到这里,可以很容易地总结出单向链表的特点:

  1. 链表由若干结点组成
  2. 每个结点由数据域和指针域组成,数据域存储数据,指针域存储下一个结点的位置
  3. 单向链表是单向的,数据存取必须从第一个结点开始
  4. 链表的最后一个结点没有后继结点,所以其指针域置为Null,表示链表结束

2.1. 头结点与头指针

头结点:即单链表的第1个存数据的结点之前的那个结点,该结点的数据域可以不存储任何信息,也可以存储如链表长度等附加信息,该结点的指针域指向第1个存数据的结点。

下面是一个带头结点的链表:

head.next是第1个存数据的结点

技术图片

下面是一个不带头结点的链表:

head是第1个存数据的结点

技术图片

头指针(head):不是一个单独的结点,而是对第1个结点的引用。它通过存储一个指向第1个结点的指针来保存整个链表

注意:第1个结点不一定是第1个存数据的结点

  • 在带头结点的单链表中,头指针指向第1个结点(头结点)
  • 在不带头结点的单链表中,头指针指向第1个结点(第1个存数据的结点)

3. 单链表的操作

在介绍下面的操作时,会分两种:带头结点的链表和不带头结点的链表。

/**
 * 结点类
 * @author Xing Xiaoguan
 */

public class Node {
    int data;
    Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }
}

3.1. 增加结点

3.1.1. 带头结点的单链表

头插法:新增加的结点放在头结点后面。头插法的结点顺序和插入顺序相反。下图是头插法的过程

技术图片

尾插法:新增加的结点放在链表的最后面。下图是尾插法的过程:

技术图片

中间插法:新增加的结点插在链表中间。下图是中间插法的过程:

技术图片

由于是单向链表,所以我们必须先找到prevNode结点,才能进行插入操作。

nextNode不是必须的,可以使用prevNode.next代替。如果这样代替了,插入操作的顺序不能变,否则prevNode结点后的所有结点都会丢失。

3.1.2. 不带头节点的单链表

头插法:新增加的结点被头指针引用。下图记录了整个过程:

技术图片

尾插法:新增加的结点放在链表的最后面。下图描述了过程:

技术图片

中间插法:不带头节点和带头结点的一样。

3.1.3. 二者比较

比较上面的动图可以看出:

不带头结点的链表在进行头插和尾插时需要考虑空链表的情况,即插入第1个结点和插入其他结点的操作不同

带头结点的链表在进行头插和尾插时不需要考虑空链表的情况,即插入第1个结点和插入其他结点的操作相同

显然带头结点的链表在进行插入操作时更方便。

3.2. 遍历链表

带头结点和不带头节点的链表在遍历时要注意遍历的起点和结束:第一个存数据的结点~最后一个存数据的结点。

带头结点的链表遍历从head.next结点开始,不带头结点的链表遍历从head开始。

//带头结点的遍历
for (Node node = head.next; node != null; node = node.next)
    System.out.print(node.data + " ");

//不带头结点的遍历
for (Node node = head; node != null; node = node.next)
    System.out.print(node.data + " ");

3.3. 查询结点

查询其实就是对遍历的应用,不管是根据下标index查询还是根据数据data查询,其实都是在遍历链表。

3.4. 删除结点

3.4.1. 带头结点的单链表

删除第一个存数据的结点:

技术图片

删除最后一个结点:

技术图片

删除中间结点:

技术图片

3.4.2. 不带头结点的单链表

删除第一个存数据的结点

技术图片

删除中间结点和删除最后一个结点的操作与带头结点的操作相同。

3.4.3. 二者比较

删除第1个存数据的结点的操作不同,删除中间结点和尾结点的操作相同。

3.5. 更新结点

更新结点是对查询的应用,查询到要更新的结点然后更新即可。

4. 代码

完整代码获取请移步码云

https://gitee.com/xingrenguanxue/code-in-blogs/tree/master/src/链表基础总结/linkedlist

如有错误,还请指正

文章首发于公众号『行人观学』
技术图片


以上是关于链表基础总结的主要内容,如果未能解决你的问题,请参考以下文章

链表的基础操作专题小归纳

力扣基础链表题总结

VsCode 代码片段-提升研发效率

Java基础知识总结 ——HashMap源码

Java基础回顾小练(基于链表实现一个IntLinkedList)

python常用代码片段总结