C语言程序设计第9章-9.2.pptx
C 语 言 程 序 设 计 实 例 教 程9.2 链表,C 语 言 程 序 设 计 实 例 教 程,第9章 结构体和共用体,动态开辟存储空间的相关函数的使用 单向链表的建立方法 链表的基本操作的相关函数的使用,本节要点实例48 单向链表的建立输出五名同学的信息,【实例任务】 定义一个结构体类型的数组,然后将这五个数组元素连接起来生成一个链表,通过每个结构体类型数组元素的指针成员输出每名同学的信息。程序运行结果如图9-6所示。,图9-6 程序运行结果实例48 单向链表的建立输出五名同学的信息,【实例任务】 include “stdio.h“ include “string.h“ typedef struct student char name20; int num; struct student *next; ST; main ST a5,*head,*p; /*定义a5是有5个元素的结构体类型的数组*/ int i; printf“请依次输入五名同学的姓名和学号n“;实例48 单向链表的建立输出五名同学的信息,【实例任务】 fori0;i5;i getsai.name; scanf“d“, /*最后一个数组元素的指针成员不再有任何指向,赋值为0*/实例48 单向链表的建立输出五名同学的信息,【实例任务】 phead;/*p先指头指针*/ printf“请输出这五名同学的个人信息n“; fori0;iname; printf“10dn“,p-num; pp-next; /*通过每个结点的next成员值,实现了链表结点的后移*/ getch; 实例48 单向链表的建立输出五名同学的信息,【相关知识】 1结构体的成员可以为指向本结构体的指针 结构体类型定义时,可以为各种固有的类型。对于构造结构体类型时,可以为指向本结构体类型的指针。实例中定义结构体类型时的next成员,是基类型为指向自身的指针变量,这样可以通过这个变量记录下一个相同类型的结构体类型变量或数组元素,从而逻辑上连接起来,生成一个链表。实例48 单向链表的建立输出五名同学的信息,2单向链表的建立 实例中,基于结构体类型构造时含有一个指向自身的指针变量,通过这个指针变量,将5个数组元素连接起来,从而通过这个指针成员来引用结构体类型数组元素的各个成员。其链表形式如图9-7所示。,图9-7 链表的构成实例48 单向链表的建立输出五名同学的信息,连接到链表的每个元素,在链表中称为结点。这些结点在存储空间的地址可以连续,也可以不连续,都是通过指针域连接到一起。 单向链表都有一个头指针,它指向链表的第一个结点,这个结点也称为链表的头结点。链表的最后一个结点为尾结点,因其指针域不再有任何指向,其指针域赋值为NULL(空),通常我们赋值为0。实例中,a4元素的指针赋值为0。实例49 动态链表的建立及常用操作输出学生的信息,【实例任务】 动态开辟存储空间,将新建立的各个结点依次链接到链表中,然后按顺序输出学生的学号和姓名信息。程序的运行结果如图9-8所示。,图9-8 程序运行结果实例49 动态链表的建立及常用操作输出学生的信息,【程序代码】 include “stdio.h“ include “string.h“ include “stdlib.h“ typedef struct student int num; char name20; struct student *next; ST;/*为结构体命别名为ST*/ main ST *head,*p,*s,new; head0*/ /*创建一个空链表,并将头指针各参数初始化*/ headmallocsizeofST;/*为头指针动态开辟存储空间*/实例49 动态链表的建立及常用操作输出学生的信息,【程序代码】 ifheadNULL printf“没有足够的内存请返回“; return; head-nextNULL; head-num0; /*在链表中插入结点*/ phead;/*p先指向头指针*/实例49 动态链表的建立及常用操作输出学生的信息,【程序代码】 do printf“请输入学生的学号为n“; scanf“d“,/*将学生存入s结点中*/实例49 动态链表的建立及常用操作输出学生的信息,【程序代码】 s-nextNULL;/*将s结点的指针域赋值为空*/ p-nexts;/*将s结点连接到链表的结尾*/ ps;/*p指向新产生的结点*/ while1; printf“结点已经插入,成功n“; phead-next;/*p指向头结点*/ whilepNULL/*只要p所指向结点的指针域不为空,循环不结束*/ printf“学生的学号为d 姓名为sn“,p-num,p-name; pp-next;/*指针逐个结点后移*/ getch; 实例49 动态链表的建立及常用操作输出学生的信息,【相关知识】 1.动态链表 对于已经存在的各个相同类型的结构体类型的变量或数组元素,可以通过指针域连接成链表。对于结构体类型的存储空间,可以在程序运行过程根据需要动态地开辟。动态链表就是这样一种能动态地进行存储空间分配的数据结构。 3free函数 系统中,为了防止资源浪费,提供了另外一个函数free,用于释放指针所指向的存储空间。该函数也在头文件“stdlib.h”中声明。其使用形式为 free指针变量;实例49 动态链表的建立及常用操作输出学生的信息,【相关知识】 2malloc函数 C语言中提供了一个函数malloc,该函数在头文件“stdlib.h”中声明,它用于根据需要动态地为链表开辟存储空间,其函数值为所开辟空间的起始地址,并赋值给一个与其数据类型相同的指针变量,其使用形式为 smallocsizeof数据类型; 如, smallocsizeofchar5; /*开辟5个字符的存储空间*/ smallocsizeofint;/*开辟2个字节的整型存储空间*/ smallocsizeofST;/*开辟1个别名为ST的结构体类型存储空间*/实例50 链表的操作学生信息管理系统,【实例任务】 建立一个目录,有6个选项,根据需要选择其中一项进行操作,来实现链表的创建、结点插入、信息查找、删除结点、浏览信息、退出功能。程序的运行结果如图9-9所示。,图9-9 程序运行结果实例50 链表的操作学生信息管理系统,【程序代码】 include “stdio.h“ include “stdlib.h“ include “string.h“ typedef struct student int num; char name20; struct student *next; ST; ST *create_list; /*创建链表,只有头指针*/ int insert_listST *head,ST *stu,int n; /*向链表插入结点,n值用于指定插入的学号*/实例50 链表的操作学生信息管理系统,【程序代码】 int delete_listST *head,ST *stu; /*从链表删除指定的结点,按姓名删除*/ ST *find_listST*head,ST *stu; /*从链表中查找结点,显示个人信息*/ void browse_listST *hea(D); /*将链表中各结点的信息全部输出*/实例50 链表的操作学生信息管理系统,【程序代码】 main ST *head,new;/*head为链表的头指针,new为新建结点*/ int number,n;/*用于选择操作选项号*/ head0 printf“1.建立学生信息链表n“; printf“2.插入一名新的学生n“; printf“3.从链表中删除学生n“; printf“4.在链表中查找学生n“; printf“5.在链表中浏览信息n“; printf“6.退出程序结束操作n“;实例50 链表的操作学生信息管理系统,【程序代码】 do scanf“d“,实例50 链表的操作学生信息管理系统,case 2 ifhead0 printf“链表尚未创建请先创建链表n“; break; do printf“请输入学生的学号n“; scanf“d“,实例50 链表的操作学生信息管理系统,case 3 printf“请输入待删除学生的姓名n“; scanf“s“,实例50 链表的操作学生信息管理系统,case 5 browse_listhea(D);/*将链表头指针作为实参传递*/ break; case 6 return; while1; getch; 实例50 链表的操作学生信息管理系统,【相关知识】 1链表的建立函数 利用malloc函数开辟一存储空间,然后对其进行初始化后将头指针返回调用处,其函数代码为 ST *create_list ST *head; headmallocsizeofST;/*为头指针动态开辟存储空间*/ ifheadNULL printf“链表已经建立成功请选择下一步操作n“; else printf“内存不足n“; head-nextNULL;/*将头指针指针域赋值为空*/ head-num0;/*num域赋值为0*/ return head; /*返回创建链表的头指针地址*/实例50 链表的操作学生信息管理系统,【相关知识】 2插入结点函数 对于已经创建的链表,可以向链表插入结点。插入过程分两种情况,一种是插入到链表结尾,另一种是指定插入位置,实例中指定插入位置n,实例中插入结点过程形如图9-10所示,其中虚线为原链表中q、p所指向结点的连接情况。,图9-10 插入结点的过程实例50 链表的操作学生信息管理系统,【相关知识】 插入结点函数代码为 int insert_listST *head,ST *stu,int n ST *q,*p,*newstu; newstumallocsizeofST;/*新开辟一空间,用于存放新插入的结点*/ ifnewstuNULL printf“内存空间不足n“; return 0; qhead; phead-next; whilepNULL 实例50 链表的操作学生信息管理系统,【相关知识】 3删除结点函数 要删除结点,首先要找到指定的结点,然后是一个断链重新接上的过程,如图9-11所示,再将被删除结点所占的存储空间释放掉,图中虚线为被删除的结点。实例50 链表的操作学生信息管理系统,【相关知识】 删除结点函数代码为 int delete_listST *head,ST *stu ST *q,*p; qhead; phead-next; whilepNULL 实例50 链表的操作学生信息管理系统,【相关知识】 4查找结点函数 查找结点函数代码为 ST *find_listST *head,ST *stu ST *p; phead; whilepNULL 实例50 链表的操作学生信息管理系统,【相关知识】 5浏览信息函数 链表将位于不同存储空间位置的相同数据结构的结点连接起来,那么可以通过移动指向各结点的指针访问各个结点。 浏览信息函数的代码为 void browse_listST *hea(D) ST *p; phead-next; whilepNULL printf“学号d 姓名sn“,p-num,p-name; pp-next; printf“请选择下一步操作n“; 【课堂精练】,1.计算一组同学的平均成绩,并统计一下不及格的人数。程序的运行结果如图9-12所示。,图9-12 程序的运行结果【课堂精练】,根据程序的运行结果,请将下面程序补充完整并调试。 include “stdio.h“ struct stu int num; char name20; float score; student510,“stu0“,65, 20,“stu1“,38, 30,“stu2“,92.5, 40,“stu3“,48.5, 50,“stu4“,76;【课堂精练】,main int i,count0; float ave,sum0.0; fori0;i5;i sumstudenti.score; ifstudenti.score60 _ printf“这组学生的平均成绩为.2fn“,sum/5; _ getch; 【课堂精练】,2建立一个结构体类型,然后动态生成几个结点并建立起链表。输出五名同学的平均成绩,并统计一下不及格学生的人数。程序的运行结果如图9-13所示。,图9-13 程序运行结果【课堂精练】,根据程序的运行结果,请将下面程序补充完整并调试。 include “stdio.h“ include “string.h“ include “stdlib.h“ typedef struct student int num; char name20; float score; struct student *next; ST;/*为结构体命别名为ST*/【课堂精练】,main ST *head,*p,*s,new; int count10,count20; float sum0.0; head0*/ /*创建一个空链表,并将头指针各参数初始化*/ headmallocsizeofST;/*为头指针动态开辟存储空间*/ ifheadNULL printf“没有足够的内存请返回“; return; head-nextNULL; head-num0; head-score0.0;【课堂精练】,/*在链表中插入结点*/ phead;/*p先指向头指针*/ do printf“请输入学生的学号为“; scanf“d“,/*开辟一个ST结构体类型的存储空间*/【课堂精练】,ifsNULL printf“没有足够的内存请返回“; return; strcpys-name,new.name;/*将姓名存入s结点中*/ s-numnew.num;/*将学生存入s结点中*/ _ s-nextNULL;/*将s结点的指针域赋值为空*/ p-nexts;/*将s结点连接到链表的结尾*/ ps;/*p指向新产生的结点*/ while1; printf“结点已经插入,成功n“;【课堂精练】,/*统计不及格学生的人数*/ phead-next;/*p指向头结点*/ whilepNULL/*只要p所指向结点的指针域不为空,循环不结束*/ sump-score; ifp-scorenext;/*指针逐个结点后移*/ printf“n这组同学的平均成绩为.2fn“,sum/count1; printf“这组同学中不及格的学生数为d“,count2; getch; 谢谢,