定义
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
简介
链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。(下图1)
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。链表最基本的结构是在每个节点保存数据和到下一个节点的地址,在最后一个节点保存一个特殊的结束标记,另外在一个固定的位置保存指向第一个节点的指针,有的时候也会同时储存指向最后一个节点的指针。一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。但是也可以提前把一个节点的位置另外保存起来,然后直接访问。当然如果只是访问数据就没必要了,不如在链表上储存指向实际数据的指针。这样一般是为了访问链表中的下一个或者前一个(需要储存反向的指针,见下期的双向链表)节点。链表的优点除了「插入删除不需要移动其他元素」之外,还在于它是一个局部化结构。就是说当你拿到链表的一个
node 之后,不需要太多其它数据,就可以完成插入,删除的操作。
具体实现
本次代码实现为单向链表,头结点为null,默认操作从头结点之后的结点开始,当插入一个新的结点之后,新节点的指针域存放的地址为这个 默认的"头结点",在加上它的两个域(数据域,指针域)的值都为null,也就是没有下一个结点了。
- 链结点:如果把链表比作火车,那个链结点就相当于每一节车厢,如图一就相当于有三个有值的链结点。每个结点中有一个数据域,一个指针域。数据域存放每个结点的具体内容,指针域存放指向下一个链结点的地址。
/*
* 链结点,相当于是车厢
*/
public class Node {
//数据域
public long data;
//指针域
public Node next;
public Node(long value) {
this.data = value;
}
/**
* 显示方法
*/
public void display() {
System.out.print(data + " ");
}
}
- 构造方法:默认的构造方法也会帮我们把成员变量初始化为null,这里写为了大家能更清楚的看出来。头个结点的值为null
- 插入结点:这里的插入操作是将具体的数据放入一个新链结点的数据域中,然后将头结点的地址,存入这个新链结点的指针域中,最后将这个新链结点赋值给头结点即可。(第一次比较特殊,会将一个null赋值给新链结点的指针域中,除此之外都是将头结点的地址存入这个新的与结点的指针域中。其实第一次也是头结点的地址,只不过为null罢了)
- 删除结点:删除链节点比较简单,只需要把下一个链结点赋值头结点,这样就使得原有的头结点跟链表失去了关系,就完成了从链表中删除的操作。
- 打印方法:做一个循环,只要本链结点的数据域不为空,那么就遍历下一个链结点。具体代码为新建一个临时变量,然后循环赋值
- 查找方法:具体行为和打印方法相似,只不过加两个判断条件,链结点数据域内容是否一致,以及下一个链结点是否为null
- 删除方法,根据数据域来进行删除:中间有一个小的细节就是,当你找到那个链结点的数据域和目标数值相等的时候,这个时候的操作就是把下一个链结点的数据域放到上一个链结点的指针域,但是你没办法在找到上一个链结点。所以要提前标注一个临时链结点保持上一个链结点。剩下的代码基本和上面差不多了
/*
* 链表,相当于火车
*/
public class LinkList {
//头结点
private Node first;
public LinkList() {
first = null;
}
/**
* 插入结点
*/
public void insertFirst(long value) {
Node node = new Node(value);
node.next = first;
first = node;
}
/**
* 删除结点
*/
public Node deleteFirst() {
Node tmp = first;
first = tmp.next;
return tmp;
}
/**
* 打印
*/
public void display() {
Node current = first;
while(current != null) {
current.display();
current = current.next;
}
System.out.println();
}
/**
* 查找方法
*/
public Node find(long value) {
Node current = first;
while(current.data != value) {
if(current.next == null) {
return null;
}
current = current.next;
}
return current;
}
/**
* 删除方法,根据数据域来进行删除
*/
public Node delete(long value) {
Node current = first;
Node previous = first;
while(current.data != value) {
if(current.next == null) {
return null;
}
previous = current;
current = current.next;
}
if(current == first) {
first = first.next;
} else {
previous.next = current.next;
}
return current;
}
}