小徒弟Karl非常想学链表,所以我打算写一篇关于单链表的入门教程。既然是入门,那就要打好基础,从头说起。所以先说“线性表”。
一、什么是线性表
线性表是具有相同特性的数据元素的一个有限序列。
该序列中所含元素的个数叫做线性表的长度,如果n
表示,那么n>=0
。
当n=0
时,表示线性表是一个空表,即表中不包含任何元素。
设序列中第i
(i表示位序)个元素为ai
(1≤i≤n)。
线性表的一般表示为:(a1,a2,…ai,ai+1,…,an)
其中a1
为第一个元素,又称做表头元素,a2
为第二个元素,an
为最后一个元素,又称做表尾元素。
例如,在线性表(1,4,3,2,8,10)
中,1为表头元素,10为表尾元素。
线性表的特点:
1、 有序
线性表里面的元素是一个挨着一个顺序排下去的,就像大家排队买票;
2、允许没有元素,也就是空表;
3、第一个元素有且仅有一个后继,最后一个元素有且仅有一个前驱,其他元素有且仅有一个前驱以及有且仅有一个后继。
二、线性表的运算
线性表有一些基本运算,举例如下:
(1) 初始化线性表——构造一个空的线性表;
(2) 销毁线性表——释放线性表占用的内存空间;
(3) 判线性表是否为空表;
(4) 求线性表的长度——返回表中元素个数;
(5) 遍历线性表——当线性表不为空时,顺序显示表中各结点的值域;
(6) 求线性表中指定位置的某个数据元素;
(7) 定位查找LocateElem(L,e):返回表L中第1个值域与e相等的位序。若这样的元素不存在,则返回值为0。
(8) 插入数据元素——在L的第i个元素之前插入新的元素e,L的长度增加1。
(9) 删除数据元素——删除L的第i个元素,L的长度减1。
三、线性表的顺序存储——顺序表
线性表只是一种逻辑结构,至于它在计算机中是如何存储的,我们还要专门讨论。因为线性表是有顺序的,所以很容易想到用数组来存储线性表。
线性表的顺序存储结构就是:把线性表中的所有元素按照其逻辑顺序依次存储到一块连续的存储空间中。
用数组来存储线性表,其缺点是:
1、在插入、删除时要移动大量的结点
2、表的大小在定义数组时指定,无法动态更改
为了克服以上缺点,有了线性表的链式存储。
四、线性表的链式存储—链表
在链式存储中,每个存储结点不仅包含元素本身的信息(称之为数据域),而且包含元素之间逻辑关系的信息,即包含其后继结点的地址信息,这称为指针域。一般地,每个结点有一个或多个这样的指针域。若一个结点中的某个指针域不需要指向任何结点,则仅它的值为空,用NULL表示。
五、单链表
在每个结点中除包含有数据域外,又设置一个指针域,用以指向其后继结点,这样的表称为线性单向链接表,简称单链表。
1、不带头结点的单链表
这种单链表必须有一个头指针(假设叫head
),用以指向单链表中第一个结点。否则单链表会在内存中丢失。
示意图如下:
2、带头结点的单链表
为了便于插入和删除等算法的实现,在单链表的第一个元素之前增加一个特殊的节点——称为头节点,头结点的数据域一般不使用,只使用其指针域。这种单链表在应用时,必须要知道头结点的地址,否则单链表会在内存中丢失。
示意图如下:
3、循环单链表
链表中最后一个结点的指针域不再是NULL
,而是指向整个链表的第一个结点或者头结点,从而使链表形成一个环。和单链表相同,循环单链表也有带头结点和不带头结点两种。
下图是带头结点的循环单链表: