单向链表
单向链表的特点是链表的链接方向是单向的,对链表的访问要通过从头部开始,依序往下读取。
节点结构
一个单向链表的节点包含两个部分,数据和指向下一个节点的指针。单向链表只可以从头开始遍历。
单向链表节点的 Java 定义
@NoArgsConstructor
@Data
public class Node<T> {
/**
* 数据
*/
private T data; 1
/**
* 指向下一个节点的指针
*/
private Node<T> next; 2
public Node(T data) {
this.data = data;
}
}
数据域:存放元素自身的数据信息。
指针域:指向节点的后继。
利用单链表可以解决数组需要大量连续存储单元的缺点,以及数组无法动态扩容的缺点。由于单链表节点离散的存储在内存中,所以无法实现对单链表的随机存取,即不能通过直接找到链表中的某个节点。在数组中可以通过元素的位置(即下标),直接找到这个元素。而在链表中却不能这样做,必须从头开始遍历,直到找到要查找的元素。
基本操作
首先定义一个单向链表的顺序表结构。
public class SingleLinkedList <T> {
/**
* 链表的头指针
*/
private Node<T> head; 3
/**
* 链表的尾指针
*/
private Node<T> tail; 4
/**
* 链表的大小
*/
private int size = 0;
}
head
指向链表的头节点,因此称为头指针。头指针指向链表的第一个节点,如果头指针为null
,则说明链表是空的。tail
指向链表的尾节点,因此称为尾指针。
提示
当链表中没有任何元素时,也即链表为空,head
和 tail
都为空,如果只有一个元素时,head
和 tail
都指向这个元素。
之所以要存储尾节点,是因为采用尾插法添加数据时,可以使时间复杂度降到 。
添加元素
链表中添加元素的方法有两种:头插法和尾插法。具体如下
头插法
头插法就是将新的元素添加到链表的头部。操作步骤如下:
- 将新节点的后继指针指向头节点
- 将头指针指向新节点
代码实现如下:
public void addFirst(T data) {
Node<T> node = new Node<>(data);
if (head == null) {
head = tail = node;
} else {
node.setNext(head); 1
head = node; 2
}
size++;
}