《第6章结构类型与联合类型.ppt》由会员分享,可在线阅读,更多相关《第6章结构类型与联合类型.ppt(104页珍藏版)》请在三一办公上搜索。
1、C语言程序设计(第3版),中国铁道出版社China Railway Publishing House,普通高等教育“十一五”国家级规划教材,主 教 材:C语言程序设计(第三版)书 号:ISBN 978-7-113-09512-3 中国铁道出版社 2009年2月 第3版配套教材:C语言程序设计实验教程书 号:ISBN 978-7-113-09513-0 中国铁道出版社 2009年2月 第1版作者电子邮箱:L,第6章 结构类型与联合类型,6.1 结构类型与联合类型概述,6.3 动态链表,6.2 结构类型,6.4 联合类型,6.5 位域类型,6.6 枚举类型,结束放映,6.1 结构类型与联合类型概述
2、,结构数据结构能直观地表示客观世界中的许多事物,是由多个不同类型的成员组装而成的复杂数据形态。这些不同类型的成员信息可以表示为基本类型的数据,也可能仍然是复杂的数据,无法直接表示为基本类型的数据,需要通过不断的数据精化,直到可以用基本类型的数据来表达为止。,结构类型的每个数据成员都需要不同的名称,为避免同结构类型的结构数据的成员名称冲突,C语言要求表示成员数据项时需要给出结构数据名,结构名与成员数据项名称间以英文园点(.)分隔。,例如:学生类型的数据组成如下表所示,用结构类型描述上述数据结构如下:typedef struct No no;Name name;Sex sex;Grade grad
3、e4;Student;4个成员数据项,分别使用了非基本的数据类型,定义类型如下:typedef char No5;typedef char Name10;typedef char Sex;typedef int Grade;,结构数据的内存分配定义一个结构类型的变量,实际上是为结构变量中的每个成员数据项分配内存空间。结构类型的变量所需分配的内存空间大小是结构类型的所有成员变量所需分配空间大小之和,可以使用运算符sizeof(结构变量名)或sizeof(结构类型名)来计算结构类型变量所需分配的空间大小。,结构数据的内存分配例如:学生类型的一个变量需要分配的内存大小可以通过sizeof(Stude
4、nt)来计算,sizeof也可以计算其它类型的内存大小,这样学生类型的变量也可以通过sizeof(No)+sizeof(Name)+sizeof(Sex)+sizeof(Grade)*4 来计算。,联合类型联合类型的定义格式与结构类型相似,但其成员变量的内存分配方式不同。联合类型的变量分配时按最大的成员变量所需内存大小来分配,所有成员变量从同一个内存地址共享内存,因此,通过取址操作&得到的成员变量的地址均相同。下图可帮助读者理解不同成员共享内存的方法:,例如:要进行学生情况调查,大学生的调查项目为专业,而中学生的调查项目为身高,其它项目均相同,这时可以使用联合方式来实现。调查表格式如下:,C语
5、言可利用联合类型表格式中的共项栏目:专业/身高项目,定义方法如下:typedef struct Name name;.Major_Height mh;Survey;typedef char Major10;typedef int Height;typedef union Major major;Height height;Major_Height;,结构类型的定义定义结构数据需要先定义结构类型,结构类型分为命名和匿名两种。定义结构类型的格式struct 结构类型名成员定义表 结构变量名表;,6.2 结构类型,说明:每个成员变量的定义与一般的变量定义一样,不能后跟初始值并以分号结束,成员变量可以
6、是基本类型也可以构造类型,所有成员变量根据定义的先后顺序分配内存。结构变量名表给出了多个标识符,以逗号分隔,每个标识符说明了一个结构变量,命名的结构类型可以省略结构变量名表,表示先只定义类型以后再使用。使用结构类型定义结构变量的格式struct 结构类型名 结构变量名表;说明:结构类型名是已定义的命名结构类型的名称,例如:struct student char no6;char name10;char sex;int grade4;a=02001,Tom,M,90,85,95,80;struct student b=02002,Jane,M,80,75,95,60;,使用typedef命令可以
7、命名一个结构类型,这种类型名不需要带上保留字struct就可以使用。格式如下:typedef struct 成员定义表 结构类型名;说明:与前面的结构类型定义方式不同,该命令只能定义结构类型不能同时定义结构变量,遵循先定义结构类型再定义结构变量的顺序。,例如:typedef char No6;typedef char Name10;typedef char Sex;typedef int Grade;typedef struct No no;Name name;Sex sex;Grade grade4;Student;Student a=02001,Tom,M,90,85,95,80,b=02
8、002,Jane,M,80,75,95,60;,匿名结构类型结构类型匿名可以建立结构类型,只是该结构类型建立后只能用一次。如果使用匿名的结构类型定义了变量,再次用同样的结构定义了另一个变量,这时,两次定义会构建两种不同的结构类型,即使这两个变量结构上完全相同,但类型却仍是不一样的。例如:struct char no6;char name10;a;struct char no6;char name10;b;,结构类型的基本操作使用结构变量中的成员结构变量中的成员变量的引用名格式:结构变量名.成员变量名说明:结构变量名是已定义的标识符,其类型中必须包含该成员变量名。成员变量名依然可以是构造类型,由
9、于成员运算符.优先级最高,使用时该引用名不用括号界定,直接像普通的变量名一样使用。该引用名可以使用结构变量内存空间中的一个数据域空间。例如:Student a;int i;for(i=1;i=4;i+)printf(“%d”,a.gradei);,【例6.1】编写程序完成结构变量的输入输出(一)#include typedef struct int month,day,year;Date;typedef struct char no6;char name10;Date birthday;Student;Student stud;/*全局变量*/,void main()char ch;do pr
10、intf(Function Menun);printf(=n);printf(1.Input Datan);printf(2.Output Datan);printf(0.Exitn);ch=getch();switch(ch)case 1:readdata();break;/*输入数据到结构变量stud*/case 2:writedata();break;/*显示结构变量stud中数据*/while(ch!=0);,【例6.1】编写程序完成结构变量的输入输出(二)void readdata()int y,m,d;printf(Please input student detail:n);pr
11、intf(=);printf(Student NO:);scanf(%s,stud.no);printf(Student Name:);scanf(%s,stud.name);printf(Birthday(Year,Month,Day):);scanf(%d,%d,%d,【例6.1】编写程序完成结构变量的输入输出(三)void writedata()int y,m,d;printf(Student detail:n);printf(=);printf(Student NO:%sn,stud.no);printf(Student Name:%sn,stud.name);y=stud.birth
12、day.year;m=stud.birthday.month;d=stud.birthday.day;printf(Birthday:%d-%d-%dn,y,m,d);printf(=n);,结构类型的基本操作使用结构变量的整体结构变量不仅可以提取成员变量使用,还可以作为一个整体来使用,作为整体使用的操作有:赋值、取址。结构变量的赋值仅限于两个结构变量之间进行。从内部机制来看,结构变量的赋值是按顺序复制结构变量的分配的内存空间中的每个字节,全部字节的内容复制完成则两个结构变量复制完成,从外部直观来看,赋值是针对变量中的每个成员变量进行的,如果成员变量是基本类型则直接赋值,如果成员变量是构造类型
13、则为分情况考虑:数组类型的成员变量会依次赋值每个数组元素;指针类型的成员变量只赋值变量中的指针值,不会赋值间接访问到的单元;结构类型的成员变量则进入结构中赋值成员变量的每个成员。,结构类型的基本操作 结构变量的取址与普通变量的取址含义一样,取出该变量在内存中的开始地址作为结果,结构变量的地址称为结构指针,结构指针可以进行指针运算,也可以间接访问结构单元,还可以间接访问结构单元中的成员变量。,【例6.2】结构变量的整体操作(一)#include struct student1 char no6;char name10;int grade3;struct student2 char*no;char
14、*name;struct int year;int month;int day;birthday;,【例6.2】结构变量的整体操作(二)void main()struct student1 a=02001,tom,70,80,60,b;struct student2 c=02002,john,1988,7,12,d;printf(No:%snName:%sn,a.no,a.name);printf(Grades:%d%d%dn,a.grade0,a.grade1,a.grade2);b=a;printf(No:%snName:%sn,b.no,b.name);printf(Grades:%d%
15、d%dn,b.grade0,b.grade1,b.grade2);printf(No:%snName:%sn,c.no,c.name);printf(Birthday:%d,c.birthday.year);printf(%d%dn,c.birthday.month,c.birthday.day);d=c;printf(No:%snName:%sn,d.no,d.name);printf(Birthday:%d,d.birthday.year);printf(%d%dn,d.birthday.month,d.birthday.day);printf(%p,%pn,a.no,b.no);prin
16、tf(%p,%pn,c.no,d.no);,结构参数函数的参数传递涉及到形参和实参,形参是设计函数时提供的一种局部变量,在函数调用时自动生成,调用结束时自动释放,实参是主程序调用函数时提供给函数处理的原始数据值,可以是常数、变量或表达式而且必须与对应位置的形参类型相同。值传递方式函数直接使用形参变量,地址传递方式函数间接使用形参变量,即通过主程序提供的地址实参找到所指向的内存单元来访问。例如,int型实参传递给形参的是实参表达式计算得到的int型值,函数直接使用该形参变量,不会使用到函数之外的内存空间;数组实参使用了数组名,数组名代表了数组第一元素的地址,作为实参传递给函数中的形参变量,函数间
17、接使用形参变量找到数组空间并访问。,【例6.3】结构数据的比较相等。(一)#include#include#include typedef struct int year;int month;int day;Birthday;typedef struct char*no;char*name;Birthday birthday;Student;,【例6.3】结构数据的比较相等。(二)int compareB(Birthday a,Birthday b)if(a.year=b.year,【例6.3】结构数据的比较相等。(三)void main()Student a=02001,tom,1988,1
18、0,6,b;b.no=(char*)malloc(6);strcpy(b.no,02001);b.name=(char*)malloc(10);strcpy(b.name,tom);b.birthday.year=1988;b.birthday.month=10;b.birthday.day=6;if(compareS(a,b)printf(compare a with b is truen);else printf(compare a with b is falsen);,结构指针 结构指针是结构类型为基类型的指针类型,也就是存放结构类型数据的内存单元的开始地址。结构数据存放在内存时是按定义
19、的先后顺序连续存放每个成员变量的数据,第一个定义的成员变量的地址也就是结构指针。结构指针变量的定义struct 结构类型名成员定义表*结构指针变量名=初始指针值;,结构指针的说明:结构类型名是用户定义的标识符,如果结构类型名已经定义,则后面没有成员定义表部分。结构指针可以参加各种指针运算,也可以间接访问所指向的结构类型的内存单元。结构指针加/减一个整数n表示指针向下/向上调整到第n个结构单元,两个同类结构的指针相减表示两个地址之间包含的结构单元的个数。间接访问结构指针所指向的结构单元的整体仍然使用*号运算符,间接访问指针所指向的结构单元的成员变量可以先使用*号运算符,再使用园点(.)运算符。,
20、【例6.4】结构指针的使用#include void main()struct student char*no;char*name;a,*p=,间接访问结构指针指向的结构单元中的成员变量格式比较繁琐,C语言提供了一种更为简单的引用机制。结构指针变量间接访问成员变量的格式结构指针变量-成员变量名说明:结构指针变量的基类型必须包含成员变量名,两者中间使用减号(-)和大于号()分隔,两个符号间不能有空,称为箭头或间接成员运算符,与成员运算符(.)具有相同的最高优先级。其含义是引用结构指针变量所指向的结构变量中的成员变量。,例如:struct student char*no;char*name;a,*
21、p=,【例6.5】结构指针的类型转换#include void main()struct student1 char*no;char*name;a;struct student2 char*no;char*name;*p=(struct student2*),结构指针参数 结构指针也可以作为函数的参数类型。将主程序中的结构变量的地址作为实参传递到函数中的结构指针形参变量,函数执行时间接访问所指向的结构变量。由于形参变量只是结构指针类型,与结构类型参数相比可以节省不少建立形参变量的堆栈内存空间,但修改主程序的变量会带来副作用。,【例6.6】用结构指针形参实现例6.3(一)#include#inc
22、lude#include typedef struct int year;int month;int day;Birthday;typedef struct char*no;char*name;Birthday birthday;Student;,【例6.6】用结构指针形参实现例6.3(二)int compareB(Birthday*p,Birthday*q)if(p-year=q-year,【例6.6】用结构指针形参实现例6.3(三)void main()Student a=02001,tom,1988,10,6,b;b.no=(char*)malloc(6);strcpy(b.no,020
23、01);b.name=(char*)malloc(10);strcpy(b.name,tom);b.birthday.year=1988;b.birthday.month=10;b.birthday.day=6;if(compareS(,动态结构变量 动态结构变量是采用动态分配命令分配的结构类型的内存空间结构指针变量可以指向该动态结构变量。要访问动态结构变量必须间接访问结构指针变量,可以使用间接访问运算(*)来访问动态结构变量的整体,也可以使用间接成员运算(-)来访问动态结构变量的成员变量。,【例6.7】结构变量的动态空间的创建与复制#include#include#include struc
24、t student char*no;char*name;void copydata(struct student*src,struct student*dest)/*dest为二级指针*/struct student*temp=(struct student*)malloc(sizeof(struct student);/*1*/temp-no=(char*)malloc(strlen(src-no)+1);/*2*/temp-name=(char*)malloc(strlen(src-name)+1);strcpy(temp-no,src-no);/*3*/strcpy(temp-name,
25、src-name);*dest=temp;/*4*/,【例6.7】结构变量的动态空间的创建与复制(续)void main()struct student a=02001,henry,*p;copydata(,结构数组结构数组是以结构数据为成员的数组。结构数组的每个成员是同类型的结构数据,所有数据成员按编号大小分配在一块连续的内存空间,编号亦称下标以零开始,是访问指定数组成员的依据。一维结构数组变量的定义struct 结构类型名成员定义表一维结构数组变量名数组大小=初始值;,结构数组说明:初始值是以花括号界定的一批结构数据值,按编号顺序为每个结构数组成员初始化,若提供的结构数据值少于数组大小,则
26、多出的数组元素使用默认值初始化:数值和字符型成员初始化为零,指针型成员初始化为NULL,字符串型成员初始化为空串,其它构造类型类似地使用默认值初始化。数组大小可以不写,只保留空的方括号,这时,后面的初始值中结构数据值的个数就是数组的大小。,【例6.8】结构数组的初始化#include struct student char no6;char name10;int grade3;void main()struct student a5=02001,tom,80,70,60,02002,john,70,90,80;int i,j;for(i=0;i=4;i+)printf(No:%stName:%
27、sn,ai.no,ai.name);printf(Grades:n);for(j=0;j=2;j+)printf(%dn,ai.gradej);,结构数组的使用下面通过一个班级学生管理的示例来介绍结构数组的使用方法。一个班级的学生是以学生为元素的数组,定义方法与例6.8相似,通常可以对班级学生完成一系列管理工作。【例6.9】编程排序班级学生#include typedef struct char no6;char name10;int grade3;Student;,【例6.9】编程排序班级学生(二)int compareS(Student a,Student b)int i,asum=0,b
28、sum=0;for(i=0;i0)temp=si;si=sj;sj=temp;,【例6.9】编程排序班级学生(三)void main()Student a30=02001,tom,80,70,60,02002,john,70,90,80,02003,henry,60,65,80,02004,susan,60,65,80,02005,mike,90,65,90;int i,j,sum;sort(a,5);for(i=0;i=4;i+)printf(No:%stName:%sn,ai.no,ai.name);printf(Sum of Grades:);for(j=0,sum=0;j=2;j+)s
29、um+=ai.gradej;printf(%dn,sum);,结构数组的使用如果需要在班级中增加或减少学生,可以在上例中增加函数即可。【例6.10】编程增删班级学生(一)#include#include typedef struct char no6;char name10;int grade3;Student;,【例6.10】编程增删班级学生(二)int compareSN(Student a,Student b)if(strcmp(a.no,b.no)=0)return 1;else return 0;int insertS(Student s,int*pnum)int i;Student
30、 x;if(*pnum=30)return 0;printf(Student NO:);scanf(%s,x.no);printf(Student Name:);scanf(%s,x.name);printf(Student Grades:);scanf(%d%d%d,【例6.10】编程增删班级学生(三)int deleteS(Student s,int*pnum)int i;Student x;if(*pnum=0)return 0;printf(Student NO:);scanf(%s,x.no);for(i=0;i=*pnum-1;i+)if(compareSN(si,x)break;
31、if(i=*pnum)return 0;for(;i=*pnum-2;i+)si=si+1;(*pnum)-;return 1;void displayS(Student s,int num)int i,j;for(i=0;i=num-1;i+)printf(No:%stName:%sn,si.no,si.name);printf(Grades:);for(j=0;j=2;j+)printf(%d,si.gradej);printf(n);,【例6.10】编程增删班级学生(四)void main()Student a30=02001,tom,80,70,60,02002,john,70,90,
32、80,02003,henry,60,65,80,02004,susan,60,65,80,02005,mike,90,65,90;int num=5;insertS(a,结构数组的使用为方便管理,主程序增设一个功能菜单【例6.11】编程实现菜单管理班级学生(一)#include#include#include void sort(Student s,int num);int insertS(Student s,int*pnum);int deleteS(Student s,int*pnum);void displayS(Student s,int num);void main()Student
33、 a30=02001,tom,80,70,60,02002,john,70,90,80,02003,henry,60,65,80,02004,susan,60,65,80,02005,mike,90,65,90;int num=5;/*下面为菜单设计*/,【例6.11】编程实现菜单管理班级学生(二)void main()do printf(Function Menun);printf(=n);printf(1.Sortn);printf(2.Insertn);printf(3.Deleten);printf(4.Displayn);printf(0.Exitn);ch=_getch();swi
34、tch(ch)case 1:sort(a,num);break;case 2:if(!insertS(a,结构数组的指针操作结构数组可以使用指针操作来查找元素的位置,指针加/减一个整数 n表示调整指针向下/向上指向第n个元素。【例6.12】编程找到数组中年龄最大的人并显示#define N 4#include stdio.hstatic struct man char name20;int age;personN=li,18,wang,19,zhang,20,sun,22;void main()struct man*q,*p;int i,m=0;p=person;m=p-age;p+;for(
35、i=1;iage)q=p;m=q-age;printf(The max age is:%s,%d,q-name,q-age);,链表的概念链表是一种序列的表示形式,表中的每个元素通过一根链相互连接,这根链是有方向的,反映了元素的先后顺序,前面的元素称为前驱,后面的元素称为后继,链中的每个元素称为结点。顺序访问链表中每个元素一次且最多一次被称为遍历或周游。链表中第一结点没有前驱信息、最后结点没有后继信息,这两个元素结点是特殊结点,保存的前驱/后继信息通常是一种判断结束位置的标志,这样,顺序访问整个链表时就能知道是否已经访问完毕。链表中的结点包含两种信息:元素的数据和元素间的前驱/后继关系,通常被
36、设计为结构类型。,6.3 动态链表,链表的概念如果链表只需要进行单向遍历,结点可以不用同时保存前驱和后继位置以便节省存储链表所需的内存空间,这种链表的实现称为单链表。如果不考虑节省结点的存储空间,则每个结点可以同时保存前驱和后继信息,这种链表的实现称为双链表,支持双向访问。让结束结点保存开始结点的位置而不是保存结束标志,也可以从任何一个结点出发找到其它结点且不浪费存储空间,这种链表的实现称为循环链表。,链表的概念为让循环链表的结束判断更简单,为让所有链中结点处理方式相同,一般在链表中增加一个额外结点,称为头结点,这样空表也会有一个结点,处理时就不用分情况了,循环链表的结束判断也更容易,只需要将
37、头结点作为结束判断的依据,这种链表的实现称为带头结点的链表。,动态链表的实现 使用指针机制表示元素间的位置关系,元素的结点空间可以根据需要动态分配,需要几个结点就在运行时分配几个,这种实现机制实现的链表称为动态链表。动态链表的结点是一种结构类型,采用动态内存分配函数分配结点所需的内存空间,其中包含有指针类型的成员变量来保存前驱/后继位置信息,也就是说,这种指针成员变量指向的是与指针成员变量所处结点类型相同的前驱/后继结点。,动态链表结点的类型定义格式struct 结点结构类型名数据成员定义表 指针成员定义表;说明:成员定义分为数据成员和指针成员,其中数据成员变量用于表示链表中的元素值,指针成员
38、变量用于保存前驱/后继元素的位置地址。链表中的每个元素要使用该类型名来动态分配内存单元,而且指针成员变量必须是指向该结点结构类型单元的指针。定义中没有结点结构类型的变量表,这是因为结点变量是动态分配建立的。,动态链表的定义格式struct 结点结构类型名数据成员定义表 指针成员定义表*动态链表变量;说明:结点结构类型名是已定义的类型名则后面的成员定义表要省略,否则需要通过成员定义表来定义动态链表的结点结构。动态链表变量是指向结点结构的指针类型,一般用来指向链表的开始结点或头结点,这样通过该变量也可以依次访问所有链表中成员。建立无头结点的动态链表时,先建立空表,即让动态链表变量为NULL,每次加
39、入新结点必须调整相关结点的前驱/后继指针成员变量的指向,并且非循环链表的结束结点的指针成员总是赋值为NULL。若是循环链表则赋值为开始结点的地址。,说明:建立带头结点的动态链表时,要建立空表则首先要建立一个头结点,并且让动态链表变量指向该头结点,头结点的指针成员变量为NULL。每次加入新结点都是加在头结点之后,不改变动态链表变量的指向,并保持链表的结束标志。例如:建立无头结点的空动态链表struct student char no6;char name10;struct student*next;*head=NULL;,【例6.13】建立动态单链表(一)#include#include typ
40、edef struct student Student;struct student char no6;char name10;Student*next;typedef Student*StudentLink;,【例6.13】建立动态单链表(二)void insert(StudentLink*phead)Student*p,*q=(Student*)malloc(sizeof(Student);printf(Student NO:);scanf(%s,q-no);printf(Student Name:);scanf(%s,q-name);if(*phead=NULL)*phead=q;q-n
41、ext=NULL;else for(p=*phead;p-next!=NULL;)p=p-next;p-next=q;q-next=NULL;void main()StudentLink head=NULL;Student*p;int i;for(i=0;inext)printf(Student No:%stStudent Name:%sn,p-no,p-name);,【例6.14】建立带头结点的动态单链表/*前面与例6.13一样*/void main()StudentLink head=(StudentLink)malloc(sizeof(Student);Student*p;int i;h
42、ead-next=NULL;for(i=0;inext;p!=NULL;p=p-next)printf(Student No:%stStudent Name:%sn,p-no,p-name);,静态链表的实现 使用数组机制,元素间的位置关系通过保存数组元素的下标来实现,由于数组的大小是编译时决定的,不能在运行时改变,这种实现方式实现的链表称为静态链表。静态链表的结点也是一种结构类型,包含了数据成员和位置成员,预先要根据所需要的结点个数上限建立一个数组,位置成员变量用来保存前驱/后继元素的数组的下标,也就是说位置成员变量是整型变量。静态链表的结点空间是利用数组机制静态定义的,数组的大小是链表中元
43、素个数的上限,每次链表要加入一个新结点则从数组中取一个元素,直到取完为止。,静态链表的实现 例如:struct student char no6;char name10;int next;int head=-1;struct student space100;int pos=100;,【例6.15】模仿例6.13,建立静态单链表(一)#include typedef int StudentPos;typedef struct char no6;char name10;StudentPos next;Student;typedef int StudentLink;Student space100
44、;int pos=100;,【例6.15】模仿例6.13,建立静态单链表(二)void insert(StudentLink*phead)StudentPos p,q=(StudentPos)-pos;printf(Student NO:);scanf(%s,spaceq.no);printf(Student Name:);scanf(%s,spaceq.name);if(*phead=-1)*phead=q;spaceq.next=-1;else for(p=*phead;spacep.next!=-1;)p=spacep.next;spacep.next=q;spaceq.next=-1;
45、,【例6.15】模仿例6.13,建立静态单链表(二)(续程序)void main()StudentLink head=-1;StudentPos p;int i;for(i=0;i=4;i+)insert(,动态链表的基本操作链表最基本的操作是建表和遍历,只有链表建立完成后才能做查找、修改、插入、删除、排序等其它基本操作,而检查链表操作是否正确就需要使用遍历操作了。,【例6.16】编程实现带头结点单链表上的建表和遍历显示操作(一)#include#include typedef struct student Student;struct student char no6;char name10
46、;Student*next;typedef Student*StudentLink;,【例6.16】编程实现带头结点单链表上的建表和遍历显示操作(二)void insert(StudentLink head)Student*p,*q=(Student*)malloc(sizeof(Student);printf(Student NO:);scanf(%s,q-no);printf(“Student Name:”);scanf(%s,q-name);for(p=head;p-next!=NULL;)p=p-next;p-next=q;q-next=NULL;StudentLink createL
47、(int num)StudentLink head=(StudentLink)malloc(sizeof(Student);int i;head-next=NULL;for(i=0;i=num-1;i+)insert(head);return head;,【例6.16】编程实现带头结点单链表上的建表和遍历显示操作(三)void displayL(StudentLink head)Student*p;for(p=head-next;p!=NULL;p=p-next)printf(Student No:%stStudent Name:%sn,p-no,p-name);void main()Stud
48、entLink head=createL(5);displayL(head);,【例6.17】编程实现带头结点单链表的求表长、定位和查找操作(一)/*数据定义部分同例6.16*/int lengthL(StudentLink head)Student*p;int len;len=0;for(p=head-next;p!=NULL;p=p-next)len+;return len;Student*locateL(StudentLink head,int i)Student*p;int pos;if(inext)pos+;return p;,【例6.17】编程实现带头结点单链表的求表长、定位和查找
49、操作(二)Student*locateLN(StudentLink head,char no)Student*p;for(p=head-next;p!=NULL;p=p-next)if(strcmp(p-no,no)=0)break;return p;void main()StudentLink head=createL(5);Student*p;printf(Number of Students:%dn,lengthL(head);p=locateL(head,2);printf(Student No:%stStudent Name:%sn,p-no,p-name);p=locateLN(h
50、ead,02004);printf(Student No:%stStudent Name:%sn,p-no,p-name);,插入结点插入一个结点到第i个元素后面的具体步骤是:首先找到第i号结点地址存放到p,然后通过q调整待插入的新结点的后继指针指向第i+1号结点,最后通过p调整第i号结点的后继指针指向新结点。其中,第i+1号结点的地址可以从第i号结点的后继指针得到。插入过程如图6-3所示:,删除结点删除第i号结点的具体步骤是:首先找到第i-1号和第i号结点的地址分别存放到p和q中,然后通过p调整第i-1号结点的后继指针指向第i+1号结点。其中,第i+1号结点的地址可以从第i号结点的后继指针得