在之前学习了线性表的顺序存储结构之后,我们知道顺序存储结构的优点就是查询和修改速度快,但是它也是有缺点的,那就是插入和删除需要移动大量的元素,显然非常的耗费时间,所以我们就需要学习新的知识来解决这个问题,那就是链式存储结构。顺序存储结构的缺点,恰恰就是链式存储结构的优点。
线性表链式存储结构定义
为了表示每个数据元素ai与其直接后继数据元素ai+1 之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。
结点
n个结点链结成一个链表,即为线性表(a1,a2,a3…,an)的链式存储结构,下图的每个结点种只包含了一个指针域,所以由这样的结点连结成的线性表称为单链表。单链表正是通过每个结点的指针域将线性表的数据元素按逻辑次序链接在一起,如下图所示,由多个结点组成了一个单链表。
头指针和头节点
头指针:指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
头节点分为两种:
- 真实头节点:存储数据
- 虚拟头节点:不存储数据
尾指针
尾指针表示该链表最后一个结点的位置,存储的是最后一个结点的地址。尾指针便于从尾部插入数据的效率,有了尾指针可以直接获取最后一位元素的指针域,然后指向新插入的结点,就完成了数据的插入。
线性表链式存储结构(LinkedList)类图
由下面的类图我们可以看出,单链表也是实现了List接口,并增加了一个Node类。
具体代码(采用虚拟头结点)
public class LinkedList<E> implements List<E>{ //实现了List接口的方法
private class Node{ //结点类
E data; //数据域
Node next; //指针域
public Node() { //构造函数,不带参数,传入null
this(null,null);
}
public Node(E data,Node next) { //带参数的构造函数
this.data = data;
this.next = next;
}
@Override
public String toString() { //重写toString方法,返回当前的数据值
return d