【时时三省】(C语言基础)建立动态链表
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省
所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。
例题1:
写一函数建立一个有3名学生数据的单向动态链表。
解题思路:
先考虑实现此要求的算法。在用程序处理时要用到动态内存分配的知识和有关函数( malloc,calloc,realloc和free函数)。
定义3个指针变量:head,pl和p2,它们都是用来指向struct Student类型数据的。先用malloc函数开辟第1个结点,并使p1和p2指向它。然后从键盘读入一个学生的数据给pl所指的第1个结点。在此约定学号不会为零,如果输入的学号为0,则表示建立链表的过程完成,该结点不应连接到链表中。先使head的值为NULL(即等于0),这是链表为“空”时的情况(即head不指向任何结点,即链表中无结点),当建立第1个结点就使head指向该结点。
如果输入的pl - > num不等于0,则输入的是第1个结点数据( n = 1 ),令head = pl,即把pl的值赋给head,也就是使head也指向新开辟的结点。pl所指向的新开辟的结点就成为链表中第1个结点。然后再开辟另一个结点并使pl指向它,接着输入该结点的数据。
如果输入的pl - > num0,则应链入第2个结点( n = 2 ),由于n1,则将pl的值赋给p2 - > next,此时p2指向第1个结点,因此执行“p2 - > next = p1”就将新结点的地址赋给第1个结点的next成员,使第1个结点的next成员指向第2个结点。接着使p2 = pl,也就是使p2指向刚才建立的结点。
接着再开辟1个结点并使pl指向它,并输入该结点的数据。在第3次循环中,由于n = 3 ( n≠1 ),又将pl的值赋给p2 - > next,也就是将第3个结点连接到第2个结点之后,并使p2 = p1,使p2指向最后一个结点。
再开辟一个新结点,并使pl指向它,输入该结点的数据。由于pl - > num的值为0,不再执行循环,此新结点不应被连接到链表中。此时将NULL赋给p2 - > next,建立链表过程至此结束,pl最后所指的结点未链入链表中,第3个结点的next成员的值为NULL,它不指向任何结点。虽然p1指向新开辟的结点,但从链表中无法找到该结点。
编写程序:
运行结果:
程序分析:
( 1 )调用creat函数后,先后输入所有学生的数据,若输入“0,0”,表示结束。函数的返回值是所建立的链表的第1个结点的地址(请查看return语句),在主函数中把它赋给指针变量pt。为了验证各结点中的数据,在main函数中输出了第1个结点中的信息。
( 2 )第3行令LEN代表struct Student类型数据的长度,sizeof是“求字节数运算符”。
( 3 )定义一个creat函数,它是指针类型,即此函数带回一个指针值,它指向一个struct Student类型数据。实际上此creat函数带回一个链表起始地址。
( 4 ) malloc ( LEN )的作用是开辟一个长度为LEN的内存区, LEN已定义为sizeof ( struct Student ) ,即结构体struct Student的长度。malloc带回的是不指向任何类型数据的指针( void *类型)。而p1,p2是指向struct Student类型数据的指针变量,可以用强制类型转换的方法使指针的基类型改变为struct Student类型,在malloc ( LEN )之前加了“( struct Student* )”,它的作用是使malloc返回的指针转换为struct Student类型数据的指针。注意括号中的“*”号不可省略,否则变成转换成struct Student类型了,而不是指针类型了。由于编译系统能实现隐式的类型转换,因此也可以直接写为p1 = malloc ( LEN );
( 5 ) creat函数最后一行return后面的参数是head ( head已定义为指针变量,指向structStudent类型数据)。因此函数返回的是head的值,也就是链表中第1个结点的起始地址。
( 6 ) n是结点个数。
( 7 )这个算法的思路是让pl指向新开辟的结点,p2指向链表中最后一个结点,把pl所指的结点连接在p2所指的结点后面,用“p2 - > next = p1”来实现。