C语言教程ch(2)_第1页
C语言教程ch(2)_第2页
C语言教程ch(2)_第3页
C语言教程ch(2)_第4页
C语言教程ch(2)_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第11章 结构体与共用体1 概述2 定义结构体类型变量的方法3 结构体变量的引用4 结构体变量的初始化5 结构体数组6 指向结构体类型数据的指针7 用指针处理链表8 共用体9 枚举类型10 用typedef定义类型本章学习目标本章学习目标理解结构体的概念和它对于编程的重要性;理解结构体的概念和它对于编程的重要性;理解理解定义结构体类型定义结构体类型和和定义结构体变量定义结构体变量的区的区别;别;能够用能够用“ . ”和和“-”分量运算符操作结构体变分量运算符操作结构体变量和指向结构体的指针变量;量和指向结构体的指针变量;能够定义并使用结构体数组;能够定义并使用结构体数组;了解共用体数据类型了解

2、共用体数据类型 ;自学了解枚举类型的使用;自学了解枚举类型的使用;了解用了解用typedef定义数据类型。定义数据类型。 概述概述v 数据的基本类型:整、实、字符。数据的基本类型:整、实、字符。v 数组是构造类型:每个元素为同一类型数组是构造类型:每个元素为同一类型v 有些问题仅用基本类型和数组来描述,无法反映有些问题仅用基本类型和数组来描述,无法反映其内在联系,如学生情况:其内在联系,如学生情况: numnamesexagescoreaddr整字符串字符整实字符串11001Zhang xinm1996. 5Shang hai12001Wang lif2098. 5Bei jing 上述数据互

3、相独立又相互关联,如:均与学号和姓上述数据互相独立又相互关联,如:均与学号和姓名关联。需要将其组合成一个有机的整体,名关联。需要将其组合成一个有机的整体,C语言可以将语言可以将由不同类型数据组成的这种数据结构组织成一个组合项,由不同类型数据组成的这种数据结构组织成一个组合项,称为称为结构体结构体(structure)。)。结构体结构体v结构体是一种结构体是一种构造构造数据类型。数据类型。 与其他高级语言中的与其他高级语言中的“记录记录”类似。类似。v定义:由定义:由相互关联相互关联的的不同数据类型不同数据类型的数据组成的的数据组成的有机整体。有机整体。v用途:为处理复杂的数据结构提供了手段。用

4、途:为处理复杂的数据结构提供了手段。 为函数间传递不同类型的参数提供了便利。为函数间传递不同类型的参数提供了便利。v关键字:关键字:struct 结构体类型定义结构体类型定义struct 结构体名结构体名 类型标识符类型标识符 成员名成员名1; 类型标识符类型标识符 成员名成员名2; .;成员类型可以是成员类型可以是基本型或构造型基本型或构造型struct是是关键字关键字,不能省略不能省略合法标识符合法标识符可省可省:无名结构体无名结构体;不能省略不能省略struct student int num; char name20; char sex; int age; float score; c

5、har addr30; namenumsexagescoreaddr2字节字节2字节字节20字节字节1字节字节4字节字节30字节字节.结构体类型结构体类型定义定义仅描述结构体的组成仅描述结构体的组成,不分配内存空间不分配内存空间 定义结构体类型变量的方法定义结构体类型变量的方法 声明结构体类型时不分配存储单元,使用该类型定声明结构体类型时不分配存储单元,使用该类型定义变量时才分配存储单元。定义变量方法义变量时才分配存储单元。定义变量方法3种:种:先声明先声明结构体结构体类型类型,再定义再定义结构体结构体变量变量struct student int num; char name20; char

6、sex; int age; float score; char addr30; struct student stu1,stu2; 定义结构体定义结构体类型类型定义结构体定义结构体变量变量真正可以使用的变量真正可以使用的变量struct 结构体名结构体名 类型标识符类型标识符 成员名;成员名; 类型标识符类型标识符 成员名;成员名; .;struct 结构体名结构体名 变量名表列变量名表列;声明结构体声明结构体类型类型的的同时同时定义结构体定义结构体变量变量只有在定义了只有在定义了结构结构体变量体变量后系统才为后系统才为其其分配内存分配内存。struct student int num; ch

7、ar name20; char sex; int age; float score; char addr30; stu1,stu2 ; 定义结构体定义结构体类型类型定义结构体定义结构体变量变量struct 结构体名结构体名 类型标识符类型标识符 成员名;成员名; 类型标识符类型标识符 成员名;成员名; .变量名表列变量名表列;直接定义结构体类型变量直接定义结构体类型变量用用无名结构体无名结构体直接直接定义变量定义变量只能一次只能一次struct 类型标识符类型标识符 成员名;成员名; 类型标识符类型标识符 成员名;成员名; .变量名表列变量名表列;struct int num; char na

8、me20; char sex; int age; float score; char addr30; stu1,stu2 ; 说明说明v结构体类型与结构体变量概念不同结构体类型与结构体变量概念不同l类型类型:不分配内存;不分配内存; 变量变量:分配内存分配内存l类型类型:不能赋值、存取、运算不能赋值、存取、运算; 变量变量:可以可以v结构体变量中的成员可单独使用,方法如普通变量;结构体变量中的成员可单独使用,方法如普通变量;v结构体可嵌套结构体可嵌套struct date int month; int day; int year;struct student int num; char nam

9、e20; struct date birthday; stu;numnamebirthdaymonthdayyearprintf (%d , sizeof (stu) ); struct student int num; char name20; struct date int month; int day; int year; birthday; stu;结果:结果:28v结构体成员名与程序结构体成员名与程序中变量名可相同中变量名可相同v结构体成员名与程序中变量名可相同,两者不代结构体成员名与程序中变量名可相同,两者不代表同一个对象。表同一个对象。 struct student int nu

10、m; char name20; float score; stu;int num;stu. numnum11.3 结构体变量的引用结构体变量的引用引用规则引用规则v 结构体变量结构体变量不能整体引用不能整体引用,只能引用变量只能引用变量成员成员结构体变量名结构体变量名.成员名成员名 成员成员(分量分量)运算符运算符优先级优先级: 1结合性结合性:从左向右从左向右struct student int num; char name20; char sex; int age; float score; char addr30;stu1,stu2; stu1.num=10; stu1.age+;stu

11、1.score=85.5;stu1.score+=stu2.score;void main() struct student int No; float score; stu1,stu2; scanf(“%d,%f”,&stu1); ( )scanf(“%d,%f”,); () printf(“%d,%f”,stu1); ( )printf(“%d,%f” ,); () stu2=stu1; () v结构体成员本身又是一个结构体类型,则需要找结构体成员本身又是一个结构体类型,则需要找到最低一级的成员。到最低一级的成员。 struct student int num; char name

12、20; struct date int month; int day; int year; birthday;stu1,stu2;numnamebirthdaymonthdayyearstu1.birthday.month=12;v结构体变量的成员与普通变量用法相同。结构体变量的成员与普通变量用法相同。 结构体变量的初始化结构体变量的初始化形式一形式一struct 结构体名结构体名 类型标识符类型标识符 成员名成员名1; 类型标识符类型标识符 成员名成员名2; .;struct 结构体名结构体名 结构体变量结构体变量=初始数据初始数据;struct stu int num; char name

13、20; int age; char addr30; struct stu a=112,“Wang Lin”, 19, “200 Beijing Road”;形式二形式二struct 结构体名结构体名 类型标识符类型标识符 成员名成员名1; 类型标识符类型标识符 成员名成员名2; . 结构体变量结构体变量=初始数据初始数据;struct stu int num; char name20; int age; char addr30; a=112,“Wang Lin”, 19, “200 Beijing Road”;形式三形式三 struct 类型标识符类型标识符 成员名;成员名; 类型标识符类型标

14、识符 成员名;成员名; .结构体变量结构体变量=初始数据初始数据;struct int num; char name20; char sex; int age; char addr30;stu1=112,“Wang Lin”,M,19, “200 Beijing Road”; #include void main() struct student long int num; char name20; char sex; char addr20; a=89031,“Li Lin”,M, “123 Beijing Road”; printf(No. :%ldnname:%snsex:%cnaddr

15、ess:%sn, a.num,,a.sex,a.addr);例例11.1 对结构体变量初始化对结构体变量初始化运行结果:运行结果:No. :89301 name:Li Lin sex:M address:123 Beijing Road 结构体数组结构体数组具有相同结构的结构体也可以组成数组具有相同结构的结构体也可以组成数组定义结构体数组:定义结构体数组:3种形式种形式形式一形式一:间接定义间接定义struct student int num; char name20; char sex; int age; ; struct student stu2;numnamesexagenu

16、mnamesexagestu0stu125B形式二形式二:直接定义直接定义struct student int num; char name20; char sex; int age; stu2;形式三形式三:直接定义直接定义struct int num; char name20; char sex; int age; stu2;结构体数组初始化结构体数组初始化struct 结构名结构名 结构数组名结构数组名数组长度数组长度=初始数据初始数据;定义数组时初始化定义数组时初始化:struct student int num; char name20; char sex; int age; ;st

17、ruct student stu3=100,“Wang Lin”,M,20, 101,“Li Gang”,M,19, 110,“Liu Yan”,F,19; 全部初始化时维数可省全部初始化时维数可省按顺序定义时:按顺序定义时:内层括号内层括号可以省略可以省略声明结构体时,对结构体数组初始化声明结构体时,对结构体数组初始化:struct student int num; char name20; char sex; int age; stu3=100,“Wang Lin”,M,20, 101,“Li Gang”,M,19, 110,“Liu Yan”,F,19; 全部初始化时维数可省全部初始化时

18、维数可省按顺序定义时:按顺序定义时:内层括号内层括号可以省略可以省略结构体数组应用结构体数组应用struct student int num; char name20; char sex; int age; ;struct student stu =100,“Wang Lin”,M,20, ; stu0.age+;strcpy(, “ ZhaoDa”);#include #include struct person char name20; int count; leader3=“Li”,0,“Zhang”,0,”Wang“,0; void main() int i,j; c

19、har leader_name20; for(i=1;i=10;i+) scanf(%s,leader_name); for(j=0;j3;j+) if(strcmp(leader_name,)=0) leaderj.count+; printf(n); for(i=0;i3;i+) printf(%5s:%dn,,leaderi.count);例例11.2 统计候选人选票统计候选人选票namecountLiZhangWang000namecountLiZhangWang433 指向结构体类型数据的指针指向结构体类型数据的指针v存放结构体首地址存

20、放结构体首地址v结构指针的运算按照结构指针的运算按照C语言的地址运算原则进行语言的地址运算原则进行.例如,结构指针加一将指向内存中下一个结构体。例如,结构指针加一将指向内存中下一个结构体。指向结构体变量的指针指向结构体变量的指针v定义形式:定义形式: struct 结构体名结构体名 *结构体指针名结构体指针名;例例 struct student *p;存放结构体变量在存放结构体变量在内存的起始地址内存的起始地址numnamesexagestupstruct student int num; char name20; char sex; int age; stu;struct student *

21、p=&stu;v使用结构体指针变量引用成员形式使用结构体指针变量引用成员形式 例例 int n; int *p=&n; *p=10; n=10struct student stu1;struct student *p=&stu1;stu1.num=101; (*p).num=101以下三种形式等价:以下三种形式等价:结构体变量名结构体变量名.成员名成员名 =101;(*结构体指针名结构体指针名).成员名成员名 (*p).num=101结构体指针名结构体指针名成员名成员名 pnum =101指向运算符指向运算符优先级优先级: 1结合方向:从左向右结合方向:从左向右( )不

22、能少!不能少!#include #include void main() struct student long int num; char name20; char sex; float score; stu_1,*p; p=&stu_1; stu_1.num=89101; strcpy(stu_1.name,Li Lin); (*p).sex=M; pscore=89.5; printf(nNo:%ldnname:%snsex:%cnscore:%fn, (*p).num,pname,pscore);例例11.3 指向结构体变量的指针的应用指向结构体变量的指针的应用v注意区分以下三

23、种运算注意区分以下三种运算 p n p n+ +p nstruct s int x; int y;data4=10,100,20,200,30,300,40,400;main( ) struct s *pointer=data; printf(“%dn”, +pointerx); printf(“%dn”,(+pointer)y); printf(“%dn”, (pointer+)x); printf(“%dn”, (pointer)y+); 运行结果:运行结果:11200 20 300 指向结构体数组的指针指向结构体数组的指针v结构体数组及其元素可用指针变量来指向结构体数组及其元素可用指针变

24、量来指向v数组首地址赋给指向结构体类型的指针变量时,数组首地址赋给指向结构体类型的指针变量时,当指针变量增当指针变量增1时,指向下一个数组元素。时,指向下一个数组元素。#include struct student int num; char name20; char sex; int age; stu3=10101,Li Lin,M,18, 10102,Zhang Fun,M,19, 10104,Wang Min,F,20;void main() struct student *p; for(p=stu;pstu+3;p+) printf(%d%s%c%dn,pnum,pname,psex,

25、page);numnamesexagestu0pstu1stu2p+1例例11.4 指向结构体数组的指针的应用指向结构体数组的指针的应用用结构体变量和指向结构体的指针作函数参数用结构体变量和指向结构体的指针作函数参数将一个结构体变量的值传递给另一函数将一个结构体变量的值传递给另一函数 ,方法有,方法有3种:种:v用结构体变量的成员作函数实参用结构体变量的成员作函数实参-值传递值传递l注意形、实的类型要一致。注意形、实的类型要一致。v用指向结构体变量或数组的指针作实参用指向结构体变量或数组的指针作实参-地址传递地址传递l传递的是结构体变量的地传递的是结构体变量的地 址。址。v用结构体变量作参数用

26、结构体变量作参数-多值传递多值传递,效率低,效率低l将结构体变量所占的内存单元的内容全部顺序传递给形参,要将结构体变量所占的内存单元的内容全部顺序传递给形参,要求形参与实参同类型。函数调用是单值传递,且形参占用内存求形参与实参同类型。函数调用是单值传递,且形参占用内存单元,若形参的值被改变,不会返回主调函数。单元,若形参的值被改变,不会返回主调函数。 #include #include #define FORMAT %dn%sn%fn%fn%fnstruct student /*定义为外部结构体类型定义为外部结构体类型*/ int num; char name20; float score3;

27、void main() void print(struct student); struct student stu; /*定义为局部结构体类型变量定义为局部结构体类型变量*/ stu.num=12345; strcpy(,Li Li); stu.score0=67.5;stu.score1=89;stu.score2=78.6; print(stu); /*结构体变量作实参结构体变量作实参*/void print(struct student stu) printf(FORMAT,stu.num,,stu.score0,stu.score1,stu.score

28、2); printf(“n”);例例11.5 结构体变量结构体变量stu有学号、姓名和有学号、姓名和3门课成绩,门课成绩, 在在main函数中赋值,在函数中赋值,在print函数中打印输出。函数中打印输出。 /* 对成员赋值也可以改为对成员赋值也可以改为scanf函数输入函数输入*/scanf(%d%s%f%f%f,&stu.num,, &stu.score0,&stu.score1,&stu.score2);无无&#include #define FORMAT %dn%sn%fn%fn%fnstruct student /*定义为外部结

29、构体类型定义为外部结构体类型*/ int num; char name20; float score3; stu=12345, Li Li,67.5,89,78.6;void main() void print(struct student * ); /*形参指向结构体的指针变量形参指向结构体的指针变量*/ print(&stu); /*实参为实参为stu的起始地址的起始地址*/void print(struct student *p) printf(FORMAT,pnum,pname,pscore0,pscore1, pscore2); /*用指针变量调用成员之值用指针变量调用成员之

30、值*/ printf(“n”); 结构体变量的指针作实参结构体变量的指针作实参 用指针处理链表用指针处理链表链表概述链表概述v数组:静态分配存储单元,容易造成内存浪费。数组:静态分配存储单元,容易造成内存浪费。v链表:是重要的数据结构,它根据需要,动态分链表:是重要的数据结构,它根据需要,动态分配内存单元配内存单元 。head1249135614751021A 1356B 1475C 1021D NULL 1249v特征:头指针变量,存放链表首地址,链表中每特征:头指针变量,存放链表首地址,链表中每个元素称结点,其内容:个元素称结点,其内容: l数据部分:可有若干项(整、实、字符、结构体类型等

31、)数据部分:可有若干项(整、实、字符、结构体类型等)l指针变量:下一结点的地址,最后一个结点(表尾)的指针变量:下一结点的地址,最后一个结点(表尾)的地址部分为地址部分为NULL。 v链表各结点的特点:链表各结点的特点:l在内存中可以不连续,访问某结点应找上一结点提供的地址,在内存中可以不连续,访问某结点应找上一结点提供的地址,每一结点有一指针变量存放下一结点的地址。每一结点有一指针变量存放下一结点的地址。l链表的每个结点实际上是一个结构体变量,它有若干成员组链表的每个结点实际上是一个结构体变量,它有若干成员组成,包括的内容有两部分:成,包括的内容有两部分:u数据部分:整、实、字符、结构体等类

32、型。数据部分:整、实、字符、结构体等类型。u指针变量:通常具有指向自身结构体类型的指针变量,指针变量:通常具有指向自身结构体类型的指针变量,此指针变量用来存放下一结点的地址,以便一环扣一环而此指针变量用来存放下一结点的地址,以便一环扣一环而形成链表。形成链表。 struct student int num; float score; struct student *next; ;其中:其中:next是成员名,是指针类型,是成员名,是指针类型, 它指向它指向struct student数据类型数据类型. 9910189. 599103909910785NULLnumscorenext简单链表简单

33、链表#include #define NULL 0 struct student long num; float score; struct student *next; ; void main( ) struct student a,b,c,*head,*p; a.num=99101;a.score=89.5; b.num=99102;b.score=90; c.num=99103;c.score=85; head=&a;a.next=&b;b.next=&c; c.next=NULL; p=head; do printf(“%ld %5.1fn”,pnum,psco

34、re); p=pnext; while(p!=NULL); 例例11.7 建立简单链表,它由建立简单链表,它由3个学生数据的结点组成。个学生数据的结点组成。 输出各结点中的数据。输出各结点中的数据。 每个结点都属于每个结点都属于struct student类型,它的类型,它的next成员存成员存放下一个结点的地址,这样一环扣一环,将各结节紧密的放下一个结点的地址,这样一环扣一环,将各结节紧密的扣在一起,最后一次循环,将扣在一起,最后一次循环,将p=pnext是将是将c结点的地址结点的地址赋给赋给p,这时,这时p指向指向c结点,然后将结点,然后将c结点的结点的num,score输出,输出,之后将

35、之后将p=pnext实际上是将实际上是将c结点的结点的next内容,即内容,即NULL赋给赋给p 再进行判断,再进行判断, p!=NULL条件不成立,循环结束。条件不成立,循环结束。 本例所有结点是在程序中定义的,不是临时开辟的,本例所有结点是在程序中定义的,不是临时开辟的,用完也不能释放,这种链表称用完也不能释放,这种链表称“静态链表静态链表”。处理动态链表所需的函数处理动态链表所需的函数为处理动态链表,为处理动态链表,C提供了开辟和释放存储单元的函数:提供了开辟和释放存储单元的函数:vmalloc函数函数l函数原型:函数原型:void *malloc(unsigned int size);

36、l作用:在动态区分配一个长度为作用:在动态区分配一个长度为size的连续空间,函数的连续空间,函数返回值是一个指向分配域起始地址的指针,如内存空间返回值是一个指向分配域起始地址的指针,如内存空间不足,返回空指针不足,返回空指针NULL。 (此处:此处:void为无确定类型为无确定类型) vcalloc函数函数l函数原型:函数原型:void *calloc(unsigned n,unsigned size);l作用:在内存动态区分配作用:在内存动态区分配n个长度为个长度为size的连续空间,函的连续空间,函数返回指向分配域起始地址的指针,若分数返回指向分配域起始地址的指针,若分 配不成功,返配不

37、成功,返回回NULL值。值。vfree函数函数l函数原型:函数原型:void free(void *p);l作用:释放由作用:释放由p指向的内存区,使这部分内存区能被其指向的内存区,使这部分内存区能被其它变量使用。它变量使用。P所指向的是最近一次所指向的是最近一次calloc或或malloc分配分配的存储区域。的存储区域。 free函数无返回值。函数无返回值。 v注:旧版本提供的注:旧版本提供的malloc和和calloc函数得到的是指函数得到的是指向字符型数据的指针。向字符型数据的指针。vANSI C提供的提供的malloc和和calloc函数规定为函数规定为void *类类型,这并不是说该

38、函数调用后无返回值,而是返回型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为一个结点的地址,该地址的类型为void(无类型或类无类型或类型不确定)型不确定),即一段存储区的首址,其具体类型无即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。法确定,只有使用时根据各个域值数据再确定。建立动态链表建立动态链表v建立动态链表:是指在程序执行过程中从无到有建立动态链表:是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。入各结点数据,并建立起前后相链的关系

39、。 例例11.8 写一函数建立一个有写一函数建立一个有3名学生数据的单向动态链表。名学生数据的单向动态链表。 v思路:思路: 设置设置3个指针变量个指针变量head、p1、p2head:指向链表头的指针变量,初始化:指向链表头的指针变量,初始化head=NULL。p1:指向后继结点的首地址的指针变量:指向后继结点的首地址的指针变量p2:指向结点成员:指向结点成员next的指针变量。的指针变量。 next的值是下一个结点的首地址。的值是下一个结点的首地址。 循环方式用循环方式用malloc函数开辟第函数开辟第1个结点。个结点。n=1p1、p2指向第指向第1结点首地址(见下页插图)结点首地址(见下

40、页插图)输入数据,如果输入数据,如果p1num !=0, 则则head=p1结点链入链表,反之不链入。结点链入链表,反之不链入。 开辟第开辟第2个结点:个结点:n=2p1指向第指向第2结点首地址。结点首地址。输入数据。输入数据。如果如果p1num !=0,链入,链入2结点,结点,方法:方法: p2next=p1(n=1)9910189.5headp1p2 为建立第为建立第3个结点做准备:个结点做准备:p2=p1,腾出,腾出p1 。(a)(n=2)headp2p19910189.59910390headp2p19910189.59910390(b)(n=2)headp2p19910189.599

41、10390(c) (n=2) 重复重复两步开辟第两步开辟第3个结点,并链入链表。个结点,并链入链表。 9910189.59910390headp2p19910785(a) n=39910189.59910390headp2p19910785(b) n=3n=n+1n=1 head=p1 p2next=p1 真真 假假(把把p1所指结点作所指结点作为第一个结点为第一个结点)(把把p1所指结点所指结点连接到表尾连接到表尾)p2=p1 (p2移到表尾)移到表尾)再开辟一个新结点,使再开辟一个新结点,使p1指向它指向它读入一个学生数据给读入一个学生数据给p1所指结点所指结点表尾结点的指针变量置表尾结点

42、的指针变量置NULL开辟一个新结点,并使开辟一个新结点,并使p1, p2指向它指向它读入一个学生数据给读入一个学生数据给p1所指向的结点所指向的结点head=NULL, n=0当读入的当读入的p1 num 不是零不是零 再开辟新结点,由于再开辟新结点,由于num数据为数据为0,退出循环。,退出循环。并使并使p2next=NULL,虽然,虽然p1指向新结点但没有指向新结点但没有链入链表。链入链表。 9910189.59910390p2p19910785(a) n=3head00009910189.59910390p2p19910785NULL(b) n=3head#include “stdio.

43、h”#include “malloc.h”#define NULL 0 #define LEN sizeof (struct student) struct student long num; float score; struct student *next; ; int n;struct student *creat(void) struct student *head; struct student *p1, *p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,&p1 num, &p1 score)

44、; head=NULL; while(p1 num !=0) n=n+1; if(n=1)head=p1; else p2 next=p1; p2=p1; p1=(struct student *)malloc (LEN); scanf(“%ld,%f”,&p1 num, & p1 score); p2 next=NULL; return(head); #include “stdio.h” /*改进后改进后*/#include “stdlib.h”#define NULL 0 #define LEN sizeof (struct student) struct student

45、long num; float score; struct student *next; ; int n;struct student *creat(void) struct student *head; struct student *p1, *p2; flot s; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,&p1 num,&s); p1 score=s; head=NULL; while(p1 num !=0) n=n+1; if(n=1)head=p1; else p2 next=p1; p2=p

46、1; p1=(struct student *)malloc (LEN); scanf(“%ld ,%f”,&p1 num,&s); p1 score=s; p2 next=NULL; return(head); 输出链表输出链表思路:思路: 设一个指针变量设一个指针变量p,找到链表第,找到链表第1个结点的地址个结点的地址(head的值),的值),p指向该结点,输出结点各成员的数指向该结点,输出结点各成员的数据,再据,再p后移后移指向下一结点。指向下一结点。NULLheadPPP=head,使使p指向第一个结点指向第一个结点 P指向的不是尾结点指向的不是尾结点 真真 假假输出输

47、出p所指向的结点所指向的结点p=p next当当p指的不是表尾指的不是表尾例例11.9 写一个输出链表的函数写一个输出链表的函数print。 void print( struct student *head) struct student *p; printf(“n Now, these %d records are :n”, n); p=head; if(head) !=NULL) do printf(“%ld, %5.2fn”, p num, p score); p=p next; while(p !=NULL); 对链表的删除操作对链表的删除操作并不真从内存中抹掉,只是把它分离,再前后结

48、点相链接。并不真从内存中抹掉,只是把它分离,再前后结点相链接。 例例11.10 写一函数删除动态链表中指定的结点。写一函数删除动态链表中指定的结点。 思路:本例以学号作为删除结点的标志(查找对象)。思路:本例以学号作为删除结点的标志(查找对象)。 设两个指针变量设两个指针变量p1和和p2。从。从head开始,开始,p1依次指向各结点查依次指向各结点查找找num值是否等于要删除结点的学号。每次下移前使值是否等于要删除结点的学号。每次下移前使p2=p1。学号相等删除该结点,直至查到表尾。学号相等删除该结点,直至查到表尾。99101headp19910399107NULL(a) 初始状态初始状态p2

49、(b) 下移一个结点下移一个结点 headp199107NULL9910199103p2=p1找到要删除的结点后:找到要删除的结点后:如果要删除的是第如果要删除的是第1结点,则结点,则head=p1next 。head指指向第二结点,第一结点脱离。向第二结点,第一结点脱离。head=p1 nextheadp1(c) 选中第一个结点选中第一个结点9910199107NULL99103如果要删除的不是第如果要删除的不是第1结点,则结点,则p2next=p1next 。P1指向的结点脱离。指向的结点脱离。还要考虑链表为空和链表中没有要删除的结点的情况。还要考虑链表为空和链表中没有要删除的结点的情况。

50、headp2p1p2 next=p1 next (d) 第二个结点被删除第二个结点被删除99107NULL9910199103 p1是要删除的结点是要删除的结点 是是 否否 链表是一个空表链表是一个空表真真 假假输出输出 空表空表p1=head 当当num p1 num 以及以及p1 所指的结点不是表尾结点所指的结点不是表尾结点p2=p1 (p2后移一个位置)后移一个位置) p1 = p1 next (p1后移一个位置)后移一个位置)输出输出“找不找不 到到”的信息的信息 P1所指是头结点所指是头结点 是是 否否head=p1 next (删除头结点)删除头结点)p2next=p1next (

51、删除一个结点)删除一个结点)struct student *del(struct student *head,long num) struct student *p1,*p2; if(head = = NULL) printf(“n list null ! n”); goto end; p1=head; while(num !=p1 num & p1 next != NULL) p2=p1; p1=p1 next; if(num = p1 num) if(p1 = = head) head=p1 next; else p2 next = p1 next; printf(“delete:

52、 %dn”,num); n=n-1; else printf(“%ld not been found ! n”,num); return(head); 对链表的插入操作对链表的插入操作v假设结点按成员的学号从小到大排列,按排序顺假设结点按成员的学号从小到大排列,按排序顺序插入结点。序插入结点。思路:思路:找到插入点后,将该点的找到插入点后,将该点的next值指向新结点,并使新值指向新结点,并使新结点的结点的next值等于断点后面结点的首地址。值等于断点后面结点的首地址。 设置设置p0、p1、p2三个指针变量。创建一个新结点,三个指针变量。创建一个新结点,p0指向其起始位置地址。指向其起始位置地

53、址。p1指向第指向第1个结点。个结点。head991019910399107NULL99102p0p1(a)准备将准备将p0插入链表中插入链表中 如果如果p0num大于大于p1num,则,则p2=p1,然后,然后p1后移一个后移一个结点。直至结点。直至p0num小于或等于小于或等于p1num。这时。这时p0所指结所指结点插在点插在p1所指结点之前。所指结点之前。head991019910399107NULL99102p0p1p2(b) 插入点位于链表中间插入点位于链表中间 p0nump1nump2=p1, p1=p1next 如果插入点在链表中间,则如果插入点在链表中间,则p2next=p0,

54、p0next=p1,新结点插入了链表。新结点插入了链表。9910399107NULLp1head9910199102p0p2(c) 链接新结点链接新结点 p0num p1nump2next=p0, p0next=p1 如果插入点位于最前面,则如果插入点位于最前面,则head=p0,p0 next=p1。99107NULLhead991009910399101p0p1(d) 结点插在表首结点插在表首 p0num p1num head=p0, p0next=p1 如果插入点位于最后面,如果插入点位于最后面,则则p1不再后移,不再后移,p1next=p0, p0next=NULLp199101991

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论