链表的种类有很多。我们常常会用到的链表有:单向链表、双向链表和循环链表。
链表不同于数组的地方在于:它的物理存储结构是非连续的,也就是说链表在内存中不是连续的,并且无序。它是通过数据节点的互相指向实现,当前节点除了存储数据,还会存储下一个节点的地址。我们不必在创建时指定链表的长度,因为链表可以无限的插入节点延伸,且插入和删除数据时,其时间复杂度都是 O(1)。
1. 单向链表
1.1 单向链表结构原理
单向链表在结构上有点向火车,你可以从“车厢 1”走至”车厢 2“,看看“车厢 2”里面都装了什么货品,但是如果你已经在“车厢 2”,想看“车厢 1”里的货品,单向链表是不能做到的,咱们继续看图说明:
1.2 单向链表 Java 实现
上面介绍了单向链表的结构,接下来用 Java 语言实现单向链表,因为这在面试中常常会让你手写一个链表出来,语言不受限制,理解了就能通用了。
首先我们需要先定义一个 Node 类,该对象代表链表中的一个节点。该对象包含了我们上述所说的 data,data 的类型我们定义成范型,这样定义的好处就是我们往该链表结构中存储任意对象,具有通用性。那么如何让这个 Node1 节点可以指向另一个 Node2 节点呢,很简单,在该 Node1 节点中存储下一个 Node2 节点对象。这样我们就可以通过 Node1 节点获取到 Node2 节点,如此嵌套,就形成了我们所要的链表结构。代码如下:
class Node<T> {
//包可见性
Node<T> next;
T data;
/**
* 构造函数
* @auther youDaily
* @description 构造一个新节点
* 新元素与链表结合节点
*/
public Node(T data) {
this.data = data;
}
@Override
public String toString() {
return data.toString();
}
}
定义完 Node 节点,让我们再定义一个链表类 LinkedList:
public class LinkedList<E> {
class Node<T> {
Node<T> next;
T data;
/**
* 构造函数
* @auther youDaily
* @description 构造一个新节点
* 新元素与链表结合节点
*/
public Node(T data) {
this.data = data;
}
@Override
public String toString() {
return data.toString();
}
}
private Node<E> head; // 链表表头
private int size; // 链表大小
public LinkedList() {
head = new Node<E>(null);
}
public Node<E> getHead() {
return head;
}
}
上述代码链表类 LinkedList 中定义了两个属性:head 是表头,size 代表链表的大小。
两个方法:构造函数和获取头节点的方法。以上就是一个完整的链表结构。说到数据结构那一定会涉及到对其增删改查。
整体的代码如下,方法功能介绍: