一、什么是链表
提到链表,我们大家都不陌生,在平时的编码中我们也或多或少地使用过这个数据结构。算法(第4版) (豆瓣)一书中对链表的定义如下:
链表是一种递归的数据结构,它或者为空(null),或者是指向一个结点(node)的引用,该节点还有一个元素和一个指向另一条链表的引用。
把以上定义用Java语言来描述大概是这样的:
public class LinkedList<Item> { private Node first; private class Node { Item data; Node next; } ... }
一个LinkedList类实例便代表了一个链表,它的一个实例域保存了指向链表中第一个结点的引用。如下图所示:
当然,以上我们所介绍的链表是single linked list(单向链表),有时候我们更喜欢double linked list(双向链表),double linked list就是每个node不仅包含指向下后一个结点的引用,还包含着指向前一个结点的引用。后文我们在介绍链表的具体实现是会对这两种链表进行更加详细地介绍。
通常来说,链表支持插入和删除这两种操作,并且删除/插入链表头部/尾部结点的时间复杂度通常都是常数级别的,链表的不足在于不支持高效的random access(随机访问)。
二、链表的实现
1. 单链表(Single-Linked List)
在上文中,我们已经简单用用Java刻画出了链表的部分结构,我们只需为以上的LinkedList类增加insert、delete等方法,便可以实现一个(单向)链表。下面我们来介绍如何向链表中插入及删除结点。
(1)插入结点
由于我们的LinkedList类中维护了一个指向first node的引用,所以在表头插入结点是很容易的,具体请看以下代码:
public void insert(Item item) { Node oldFirst = first; first = new Node(); first.item = item; first.next = oldFirst; itemCount++; }
(2)删除结点
在表头删除结点的代码也很简单,基本是自注释的: