- 软件工程专业大一新生,在学习c语言时,可能水平不够高,没有遇见特别难的问题,例如一些基本的语法和后边的一些简单点数据类型。后边在c语言基本够用的情况下,我开始了对数据结构与算法进行学习。买了一本很经典的教材,在学习数据结构与算法的第一章,就遇到了链表这个贵物。
- 首先,链表的基本特点以及实现的功能,是简单明了的。从互联网上,从书中明白的。用我自己的语言来表示出,我认为它就是一堆分布在内存的零碎东西,然后通过一个一个节点来进行连接的,相较于数组的实现,它更容易对内部数据进行操作,不像数组那样,是一串排列有序且分配好的数字集合,这是比较浅薄的认识。
- 然后,就是对链表这个抽象的东西进行具体化的认识,用文字来表示就是,一个大的结构体中,分为俩区,一个名字叫做数据区,一个叫做指针区(用来访问下一个节点的地方),每一个像这样的结构的结构体,穿成串儿给他们连接起来,最终成为链表。
- 其次,遇到了对链表代码实现的难以理解,我认为这是我遇见最棘手的问题,要想对代码的实现,我必须首先对前置内容,也就是结构体和指针进行熟练的理解并且能够运用行云流水,不幸的是,我学习结构体时,认为这种东西不如其他的重要,只是刷了几道题就草草而过。结构体的地基不牢,导致我对链表代码实现的内容一脸懵,深入了解过后,我明白了typedef在给结构体起别名时的便利性,我懂的了结构体在数据类型中有着与int , char ,float 等类型相同的地位,只不过它是自定义的数据类型,这样理解下来,有了更深的认知,那就意味着结构体同样可以赋予一个指针来接收到它的地址,同样可以起一个变量名称,懂得了这些,我对链表有了更新的理解。
拿一个例子来说,在用链表储存三个学生的数据c语言描述代码来说
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct students //对别名进行命名
{
int grade;
struct students *next;
}stu; // struct students 与 stu 在typedef的情况下同等地位,
int main() // 同样,stu与char ,int 具有相同的功能
{
stu *s1=(stu*)malloc(sizeof(stu)); //这里实现动态分配内存与刚才说链表零碎分布契合
stu *s2=(stu*)malloc(sizeof(stu));
stu *s3=(stu*)malloc(sizeof(stu));
stu *head=s1;
s1->grade=10; //这里对其进行赋值
s2->grade=11;
s3->grade=13;
s1->next=s2; //将每个链接连接起来
s2->next=s3;
s3->next=NULL; //最后一个节点让其指向空的,方便后边对链表每个节点进行遍历
while(head!=NULL)
{
printf("%d\t",head->grade);
head=head->next; // 这是后边要重点讲解的地方
}
free(s1);
free(s2); //防止内存泄露
free(s3);
return 0;
}
这个例子让我对这个链表有了更深的认知,同样我标记重点讲解的地方,这是我困扰的重要问题,起初我认为在结构体中这个语句 struct students *next,能够访问下一个几点是因为next确实起作用了,但在while循环中,你们也看到了,如果这样来想的话,为什么不是head->next=head呢,经过网络资料的检索与chatgpt3.5的回答,我突然意识到我这样想是错误的,再看结构体中定义的指针next,这个next指针是确确实实开辟了一块儿内存,然后把s2的结构体传入进去,从而对链表进行了连接,以此类推,整个链表因此连接到一块儿。再看head=head->next这条语句,所谓head->next实际上它是每个节点的s1->next,也可以是s2->next,s3->next的,简单来说这块地址是存在的,并且对head这个原地址进行覆盖,并不是因为next的存在,而是面表进行遍历的,所以当head=head->next这样出现的时候,就等同于第二个结构体的地址,从而实现对于链表的遍历。
这是我学链表最新的收货以及所感,以上内容是我个人所感,如果有异议,不要吝啬你们的笔墨,本人新生,望大家指导批评。。