要建立一个班级的学生信息表,根据之前所学的知识,用结构数组(数组元素为结构)来实现。例如如下代码:
typedef struct student
{
char ID[10];
char name[10];
char sex;
float score;
}STUDENT;
STUDENT stu[30] = {
{"202001", "张三", 'M', 85}
{"202002", "李四", 'F', 90}
};
数组是最基本的构造类型,它是一组相同类型数据的有序集合。数组中的元素在内存中连续存放。学过数据结构这门课程,就会知道,数组实质是一种线性结构的顺序表示方式。即数组最大特点是连续,顺序。这样方便存取线性表中的任意一元素。但是我们也会发现数组作为数据类型的一些缺点,比如说,我要插入一个元素时,造成后面所有元素后移一位。而删除一个元素时,造成后面所有元素前移一位。同时应该注意到,我们在定义数组时要指定数组长度,定义数组长度过小时造成实际使用的数组元素个数超过最大长度发生溢出,而定义的数组长度过大造成系统资源的浪费。
既然数组由这些缺点,哪么有没有一种物理存储结构上非连续、非顺序的存储结构呢?我们今天要学习的链表就是这样的一种结构。
一.单链表类型定义
单链表是由一连串的结构(称为结点)组成的,其中每个结点都包含指向下一结点的指针(单链表最后一个结点因其没有下一个结点,故单链表最后一个结点的指针为空)。即一般情况下,每个结点包括两部分,一部分是数据域,存储相关数据;另一部分是指针域,存取下一结点的地址(最后一个结点没有指针域)。
在此区别结构数组,结构数组也是由一连串的结构组成,但是这种组成是连续的,有顺序的。而且结构数组中每个结构是没有指针域的,因为其是顺序存放的,不需要指明下一结构的地址。
逻辑图如下图所示:
总结:顺序存储结构要求所有元素在内存中相邻存放,因而需占用一段连续的存储空间;而链式存储结构不是这样,每个结点单独存储,无需占用一整块存储空间,但是为了表示结点之间的关系,每个结点的后面附加指针(用于存放下一结点的存储地址),指向下一结点。
接下来要为链表中的结点声明类型,简单起见,先假设结点只包含一个int型整数(即结点的数据域)和指向表中下一结点的指针(指针域),则结点的结构可如下描述:
struct node //单链表的本质是一连串的结构,所以用关键字struct
{
int data;//结构包括数据域和指针域
struct node *next;//定义一个指针变量,存放一个结点的地址。即指向下一结点的指针
}
上面定义了一个名为node(结点)的结构类型