在上一篇文章中开始了我对大一C语言实验的记录,这篇文章将记录该实验中技术栈最关键新手掌握起来最困难的一个部分——链表。
链表可谓让很多初学者望而生畏。但循序渐进不会感到吃力。
要学习链表首先要学习C语言指针、结构体等内容。关于我学习C语言对内存地址的操作的记录会另写,此处不做赘述。链表分为单链表、双链表、单向循环链表、双向循环链表。链表顾名思义由一个个结点连接而成的一条链。
在我做实验时采用了最简单的单链表,其他更复杂的链表自然具备单链表的功能。
单链表呈现在代码上就是结构体的嵌套,结构体包含的数据类型为一个外来结构体变量data以储存数据和自身结构体指针pnext储存下一结点的地址(尾结点该变量为NULL)。当然在变量较少的时候外来结构体变量data可以直接声明为基本数据类型。
图为我的card_service.h头文件,里面包含了对链表的初始化及基本操作函数。对链表的操作大概包括新建链表、结点的插入和链表删除释放等。而结点的插入又可以分为头插入、尾插入和中间插入。中间插入当然不是指随意插入,通常对结点的顺序有要求时会选择中间某一合适的位置插入。
图中
CardList* Creat_Card_List();//新建链表操作
新建链表主要是通过开辟一块内存空间用于存放链表的头结点,为后续信息结点的插入做准备。
CardList* p;
p = (CardList*)malloc(sizeof(CardList));
if (p == NULL)
printf("内存申请失败");
上述几行代码就是为链表的头结点开辟内存空间。其中if语句是一种习惯性写法,删除不影响编译,只是为了程序的稳定性,通常会加入该if语句防止内存申请失败后对空指针的操作导致程序崩溃。
链表的头结点就类似数组下标为0的那一位,既可以用于储存数据,也可以“闲置”备用或用于存放一些特殊的数据
根据个人习惯,我将头结点也作为了存放信息的一个结点(第一次建链表,觉得以后还是空着舒服),利用简单的格式化输入函数即可读取新建卡的信息。
为了使新建链表的程序更加简明扼要,部分教程推荐将开辟内存后的一步——创建卡放入“插入卡函数”中,再让新建链表函数调用它。
上图主要是对变量的声明和初始化,虽然我在新建链表函数中看似已经创建了卡,但我还是调用了InserCard()函数,目的是让链表的每一个结点都是由插入函数实现,对我个人理解起来更加流畅罢了,纯属个人偏好。
那么按照我的思路,新建卡无非就是向链表插入了一个新节点,只是这个新节点作为链表的头。
该程序段明显能看出插入函数的逻辑,if-else语句把插入新结点分为了两种情况。
当链表已存在时,新节点将插入至链表尾部。