单链表的定义和特点
顺序表时使用一维数组作为存储结构的线性表,其特点是用物理位置上的邻接关系来表示结点间的逻辑关系,而链表是采用链接方式存储的线性表,其特点是通过各结点的链接指针来表示结点间的逻辑关系,适用于插入或删除频繁,存储需求不定情形。
1.单链表的定义
单链表(Singly linked list)也称为线性链表或单向链表。它是线性表的链接存储表示。使用单链表存储线性表,各个数据元素可以相继存储,也可以不相继存储,不过它为每个数据元素附加了一个链接指针,并形成一个一个结点(node)。通过这些指针把各个数据元素按其逻辑顺数勾连起来。
因此,单链表的每一个结点包含两个部分:data和link。其中,data部分称为数据域,用于存储线性表的一个数据元素;link部分称为指针域或链域,用于存放一个指针,用于记录该结点在链表中下一个结点的开始存储地址。
一个线性表(a1,a2,a3,…,an)的单链表结构的示意图如下图所示:
其中,链表的第一个结点(亦称为首元结点)的地址可以通过链表的头指针first找到,其他结点的地址则在前趋结点的link域中,链表的最后一个结点么有后继,在结点的link域中放一个空指针NULL(在图中用符号ˆ表示)收尾,NULL在<iostream.h>中被定义为数值0.因此,对单链表中任一结点的访问必须首先根据头指针找到首元结点,再按有关各结点link域中存放的指针顺序往下找,直到找到所需的结点。
头指针first为空的单链表为空表,该链表一个结点也没有;相应地,头指针first不为空且首元结点存在的单链表为表空表,表中至少有一个结点。
2.单链表的特点
- 单链表中数据元素的逻辑顺序与其物理顺序可能不一致,一般通过单链表的指针将各个数据元素按照线性表的逻辑顺序链接起来。
- 单链表的长度可以扩充。例如有一个连续的可用存储空间,如下表(a)所示,指针avail只是当前可用空间的开始地址。当链表要增加一个新的结点时,只要可用存储空间允许,就可以为链表分配一个结点空间,供链表使用。如下表(b)所示:
- 对单链表的遍历或查找只能从头指针指示的首元结点开始,跟随链接指针逐个结点进行访问,不能如同孙处表那样直接访问某个指定结点。
- 当进行插入或删除运算时,只需修改相关结点的指针域即可,既方便又省时。
- 由于链接表的每个结点带有指针域,因而比顺序表需要的存储空间多。
单链表的结构定义
一个单链表包含了0个或多个结点,因此一个类型为LinkList的单链表对象包含有0个互殴多个类型为LinkNode的链表结点。用C语言描述单链表的结构如下程序所示:
[程序 2-15] 单链表的结构定义
typedef int DataType;
typedef struct node{ //链表结点
DataType data; //数据域
struct node*link; //链接指针域
}LinkNode,*LinkList;
单链表中指针的操作
指针的操作在后续章节经常出现,为用好指针,本节对常用的指针操作加以总结。常用的指针操作如下表所示,假如有两个定义为LinkNode *p,*q的指针,DataType为int型。
指针p进到下一个结点(错误)p++; | 错误,指针p进到物理上的下一结点,此结点不一定是链表逻辑上的下一结点 |
---|---|
提取指针p所指结点保存的数据 i=*p; | 错误,指针p所指结点有两个域,取的是哪个域不清楚 |
指针所指结点间传送数据 *p=*q; | 错误,理由同上,需要分别对结点的每个域赋值 |