- 学习一个新东西之前,得先了解它的概念,它是什么?
动态链表
官方定义:为了表示每个数据元素ai与其直接后继数据元素ai+1 之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。
- 我的理解呢就是,它就是由多个结点连接起来的一个线性表。
结点
如图所示:
这里的结点就是数据域+指针域,数据域存储着信息,指针域它存储着下一个结点的地址,n个结点(an 的存储映像)链结成一个链表,即为线性表(a1, a2, …,an)的链式存储结构,每个结点中只包含一个指针域, 所以叫做单链表。
- 如果向对其进行查询呢?因为我们不知道每个结点的指针域存储的下一个结点是谁的地址,这里要用到头节点和尾结点。
头结点和尾结点
头结点:我们可以把链表中的第一个结点当作头节点,而头结点又分为真实头结点和虚拟头结点,真实头结点之所以真实,因为它 存储着元素又存储着下一个元素的地址,而虚拟头节点只存在着下一个结点的地址,但它两都是结点。如图:
尾结点:善始善终,有头有尾,尾结点表示链表最后一个结点的位置,用于方便我们遍历,或者说角标越界的判定。而如果你要找目标结点位置的话,你必须得先找到目标结点的前一个结点。
链表实现线性表
之前写的博客使用数组实现的线性表,现在我们用链表实现List,List接口方法之前实现过,API里List接口下有一个LinkedList子类就是用链表实现的,而上面说到连边是由结点链接而成,所以得写一个Node的内置类。看类图:
上面我们还说到如果要向链表里面更新元素,比如插入一个元素和删除一个元素。先把思路捋清楚再写代码,代码用的是虚拟头结点。
- 插入元素(三种插入方式)
头插:如果我们要插入元素A,将元素A看为一个结点。将虚拟头结点的下一跳给A结点的下一跳,然后A结点的地址给头结点的下一跳,再将A结点的下一跳给B。
尾插:在尾部插入一个元素B,先将B看为一个结点,然后将B的地址赋给当前尾节点的下一跳,然后将rear指针后移。
一般插入:也可以理解为在中间插入。我们在C之前插入一个结点B,我们应该先找到C结点的上一个结点A,然后将A结点的