C语言教程课件ch11数学

上传人:hs****ma 文档编号:591563840 上传时间:2024-09-18 格式:PPT 页数:54 大小:803.06KB
返回 下载 相关 举报
C语言教程课件ch11数学_第1页
第1页 / 共54页
C语言教程课件ch11数学_第2页
第2页 / 共54页
C语言教程课件ch11数学_第3页
第3页 / 共54页
C语言教程课件ch11数学_第4页
第4页 / 共54页
C语言教程课件ch11数学_第5页
第5页 / 共54页
点击查看更多>>
资源描述

《C语言教程课件ch11数学》由会员分享,可在线阅读,更多相关《C语言教程课件ch11数学(54页珍藏版)》请在金锄头文库上搜索。

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

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

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

4、复杂的数据结构提供了手段。为函数间传递不同类型的参数提供了便利。为函数间传递不同类型的参数提供了便利。v关键字:关键字:struct结构体类型定义结构体类型定义struct结构体名结构体名类型标识符类型标识符成员名成员名1;类型标识符类型标识符成员名成员名2;.;成员类型可以是成员类型可以是基本型或构造型基本型或构造型struct是是关键字关键字,不能省略不能省略合法标识符合法标识符可省可省:无名结构体无名结构体;不能省略不能省略注意:这只是声明一种数注意:这只是声明一种数注意:这只是声明一种数注意:这只是声明一种数据类型并没有定义变量。据类型并没有定义变量。据类型并没有定义变量。据类型并没有

5、定义变量。structstudentintnum;charname20;charsex;intage;floatscore;charaddr30; namenumsexagescoreaddr2字节字节2字节字节20字节字节1字节字节4字节字节30字节字节.结构体类型结构体类型定义定义仅描述结构体的组成仅描述结构体的组成,不分配内存空间不分配内存空间11.2 定义结构体类型变量的方法定义结构体类型变量的方法声明结构体类型时不分配存储单元,使用该类型定声明结构体类型时不分配存储单元,使用该类型定义变量时才分配存储单元。定义变量方法义变量时才分配存储单元。定义变量方法3种:种:先声明先声明结构体结

6、构体类型类型,再定义再定义结构体结构体变量变量structstudentintnum;charname20;charsex;intage;floatscore;charaddr30; structstudentstu1,stu2;定义结构体定义结构体类型类型定义结构体定义结构体变量变量真正可以使用的变量真正可以使用的变量struct结构体名结构体名类型标识符类型标识符成员名;成员名;类型标识符类型标识符成员名;成员名;.;struct结构体名结构体名变量名表列变量名表列;声明结构体声明结构体类型类型的的同时同时定义结构体定义结构体变量变量只有在定义了只有在定义了结构结构体变量体变量后系统才为后

7、系统才为其其分配内存分配内存。structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;定义结构体定义结构体类型类型定义结构体定义结构体变量变量struct结构体名结构体名类型标识符类型标识符成员名;成员名;类型标识符类型标识符成员名;成员名;.变量名表列变量名表列;直接定义结构体类型变量直接定义结构体类型变量用用无名结构体无名结构体直接直接定义变量定义变量只能一次只能一次struct类型标识符类型标识符成员名;成员名;类型标识符类型标识符成员名;成员名;.变量名表列变量名表列;structint

8、num;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;说明说明v结构体类型与结构体变量概念不同结构体类型与结构体变量概念不同l类型类型:不分配内存;不分配内存;变量变量:分配内存分配内存l类型类型:不能赋值、存取、运算不能赋值、存取、运算;变量变量:可以可以v结构体变量中的成员可单独使用,方法如普通变量;结构体变量中的成员可单独使用,方法如普通变量;v结构体可嵌套结构体可嵌套structdateintmonth;intday;intyear;structstudentintnum;charname20;structdateb

9、irthday;stu;numnamebirthdaymonthdayyearprintf(%d,sizeof(stu);structstudentintnum;charname20;structdateintmonth;intday;intyear;birthday;stu;结果:结果:28v结构体成员名与程序结构体成员名与程序中变量名可相同中变量名可相同v结构体成员名与程序中变量名可相同,结构体成员名与程序中变量名可相同,两者不代两者不代表同一个对象。表同一个对象。structstudentintnum;charname20;floatscore;stu;intnum;stu.numnum

10、11.3结构体变量的引用结构体变量的引用引用规则引用规则v结构体变量结构体变量不能整体引用不能整体引用,只能引用变量只能引用变量成员成员结构体变量名结构体变量名.成员名成员名成员成员(分量分量)运算符运算符优先级优先级:1结合性结合性:从左向右从左向右structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;stu1.num=10;stu1.age+;stu1.score=85.5;stu1.score+=stu2.score;voidmain()structstudentintNo;floats

11、core;stu1,stu2;scanf(“%d,%f”,&stu1);( )scanf(“%d,%f”,&stu1.No,&stu1.score);()printf(“%d,%f”,stu1);( )printf(“%d,%f”,stu1.No,stu1.score);()stu2=stu1;()v结构体成员本身又是一个结构体类型,则需要找结构体成员本身又是一个结构体类型,则需要找到最低一级的成员。到最低一级的成员。structstudentintnum;charname20;structdateintmonth;intday;intyear;birthday;stu1,stu2;numna

12、mebirthdaymonthdayyearstu1.birthday.month=12;v结构体变量的成员与普通变量用法相同结构体变量的成员与普通变量用法相同。11.4 结构体变量的初始化结构体变量的初始化形式一形式一struct结构体名结构体名类型标识符类型标识符成员名成员名1;类型标识符类型标识符成员名成员名2;.;struct结构体名结构体名结构体变量结构体变量=初始数据初始数据;structstuintnum;charname20;intage;charaddr30;structstua=112,“WangLin”,19,“200BeijingRoad”;形式二形式二struct结构

13、体名结构体名类型标识符类型标识符成员名成员名1;类型标识符类型标识符成员名成员名2;.结构体变量结构体变量=初始数据初始数据;structstuintnum;charname20;intage;charaddr30;a=112,“WangLin”,19,“200BeijingRoad”;形式三形式三struct类型标识符类型标识符成员名;成员名;类型标识符类型标识符成员名;成员名;.结构体变量结构体变量=初始数据初始数据;structintnum;charname20;charsex;intage;charaddr30;stu1=112,“WangLin”,M,19,“200BeijingRo

14、ad”;#includevoidmain()structstudentlongintnum;charname20;charsex;charaddr20;a=89031,“LiLin”,M,“123BeijingRoad”;printf(No.:%ldnname:%snsex:%cnaddress:%sn,a.num,a.name,a.sex,a.addr);例例11.1对结构体变量初始化对结构体变量初始化运行结果:运行结果:No.:89301name:LiLinsex:Maddress:123BeijingRoad11.5 结构体数组结构体数组具有相同结构的结构体也可以组成数组具有相同结构的结

15、构体也可以组成数组定义结构体数组:定义结构体数组:3种形式种形式形式一形式一:间接定义间接定义structstudentintnum;charname20;charsex;intage;structstudentstu2;numnamesexagenumnamesexagestu0stu125B形式二形式二:直接定义直接定义structstudentintnum;charname20;charsex;intage;stu2;形式三形式三:直接定义直接定义structintnum;charname20;charsex;intage;stu2;结构体数组初始化结构体数组初始化struct结构名结构

16、名结构数组名结构数组名数组长度数组长度=初始数据初始数据;定义数组时初始化定义数组时初始化:structstudentintnum;charname20;charsex;intage;structstudentstu3=100,“WangLin”,M,20,101,“LiGang”,M,19,110,“LiuYan”,F,19;全部初始化时维数可省全部初始化时维数可省按顺序定义时:按顺序定义时:内层括号内层括号可以省略可以省略声明结构体时,对结构体数组初始化声明结构体时,对结构体数组初始化:structstudentintnum;charname20;charsex;intage;stu3=1

17、00,“WangLin”,M,20,101,“LiGang”,M,19,110,“LiuYan”,F,19;全部初始化时维数可省全部初始化时维数可省按顺序定义时:按顺序定义时:内层括号内层括号可以省略可以省略结构体数组应用结构体数组应用structstudentintnum;charname20;charsex;intage;structstudentstu=100,“WangLin”,M,20,;stu0.age+;strcpy(stu0.name,“ZhaoDa”);#include#includestructpersoncharname20;intcount;leader3=“Li”,0

18、,“Zhang”,0,”Wang“,0;voidmain()inti,j;charleader_name20;for(i=1;i=10;i+)scanf(%s,leader_name);for(j=0;j3;j+)if(strcmp(leader_name,leaderj.name)=0)leaderj.count+;printf(n);for(i=0;i3;i+)printf(%5s:%dn,leaderi.name,leaderi.count);例例11.2统计候选人选票统计候选人选票全局结构体数组全局结构体数组“ “.” .”成员运算符优先于成员运算符优先于“ “+”+”,所以所以Lea

19、derj.count+Leaderj.count+相当于相当于( (learerj.countlearerj.count)+)+namecountLiZhangWang000namecountLiZhangWang43311.6 指向结构体类型数据的指针指向结构体类型数据的指针v存放结构体首地址存放结构体首地址v结构指针的运算按照结构指针的运算按照C语言的地址运算原则进行语言的地址运算原则进行.例如,结构指针加一将指向内存中下一个结构体。例如,结构指针加一将指向内存中下一个结构体。指向结构体变量的指针指向结构体变量的指针v定义形式:定义形式:struct结构体名结构体名*结构体指针名结构体指针

20、名;例例structstudent*p;存放结构体变量在存放结构体变量在内存的起始地址内存的起始地址numnamesexagestupstructstudentintnum;charname20;charsex;intage;stu;structstudent*p=&stu;v使用结构体指针变量引用成员形式使用结构体指针变量引用成员形式例例intn;int*p=&n;*p=10;n=10structstudentstu1;structstudent*p=&stu1;stu1.num=101;(*p).num=101以下三种形式等价:以下三种形式等价:结构体变量名结构体变量名.成员名成员名stu

21、.num=101;(*结构体指针名结构体指针名).成员名成员名(*p).num=101结构体指针名结构体指针名成员名成员名pnum=101指向运算符指向运算符优先级优先级:1结合方向:从左向右结合方向:从左向右()不能少!不能少!#include#includevoidmain()structstudentlongintnum;charname20;charsex;floatscore;stu_1,*p;p=&stu_1;stu_1.num=89101;strcpy(stu_1.name,LiLin);(*p).sex=M;pscore=89.5;printf(nNo:%ldnname:%sn

22、sex:%cnscore:%fn,(*p).num,pname,stu_1.sex,pscore);例例11.3指向结构体变量的指针的应用指向结构体变量的指针的应用v注意区分以下三种运算注意区分以下三种运算p np n+p nstructsintx;inty;data4=10,100,20,200,30,300,40,400;main()structs*pointer=data;printf(“%dn”,+pointerx);printf(“%dn”,(+pointer)y);printf(“%dn”,(pointer+)x);printf(“%dn”,(pointer)y+);运行结果:运行

23、结果:1120020300取取x x值加值加1 1后输出后输出地址加地址加1 1后再取后再取y y值值先取先取x x值地址再加值地址再加1 1y y值输出后再加值输出后再加1 1指向结构体数组的指针指向结构体数组的指针v结构体数组及其元素可用指针变量来指向结构体数组及其元素可用指针变量来指向v数组首地址赋给指向结构体类型的指针变量时,数组首地址赋给指向结构体类型的指针变量时,当指针变量增当指针变量增1时,指向下一个数组元素。时,指向下一个数组元素。#includestructstudentintnum;charname20;charsex;intage;stu3=10101,LiLin,M,1

24、8,10102,ZhangFun,M,19,10104,WangMin,F,20;voidmain()structstudent*p;for(p=stu;pstu+3;p+)printf(%d%s%c%dn,pnum,pname,psex,page);numnamesexagestu0pstu1stu2p+1例例11.4指向结构体数组的指针的应用指向结构体数组的指针的应用用结构体变量和指向结构体的指针作函数参数用结构体变量和指向结构体的指针作函数参数将一个结构体变量的值传递给另一函数将一个结构体变量的值传递给另一函数,方法有,方法有3种:种:v用结构体变量的成员作函数实参用结构体变量的成员作函

25、数实参-值传递值传递l注意形、实的类型要一致。注意形、实的类型要一致。v用指向结构体变量或数组的指针作实参用指向结构体变量或数组的指针作实参-地址传递地址传递l传递的是结构体变量的地传递的是结构体变量的地址。址。v用结构体变量作参数用结构体变量作参数-多值传递多值传递,效率低,效率低l将结构体变量所占的内存单元的内容全部顺序传递给形参,要将结构体变量所占的内存单元的内容全部顺序传递给形参,要求形参与实参同类型。函数调用是单值传递,且形参占用内存求形参与实参同类型。函数调用是单值传递,且形参占用内存单元,若形参的值被改变,不会返回主调函数。单元,若形参的值被改变,不会返回主调函数。#includ

26、e#include#defineFORMAT%dn%sn%fn%fn%fnstructstudent/*定义为外部结构体类型定义为外部结构体类型*/intnum;charname20;floatscore3;voidmain()voidprint(structstudent);structstudentstu;/*定义为局部结构体类型变量定义为局部结构体类型变量*/stu.num=12345;strcpy(stu.name,LiLi);stu.score0=67.5;stu.score1=89;stu.score2=78.6;print(stu);/*结构体变量作实参结构体变量作实参*/voi

27、dprint(structstudentstu)printf(FORMAT,stu.num,stu.name,stu.score0,stu.score1,stu.score2);printf(“n”);例例11.5结构体变量结构体变量stu有学号、姓名和有学号、姓名和3门课成绩,门课成绩,在在main函数中赋值,在函数中赋值,在print函数中打印输出。函数中打印输出。/*对成员赋值也可以改为对成员赋值也可以改为scanf函数输入函数输入*/scanf(%d%s%f%f%f,&stu.num,stu.name,&stu.score0,&stu.score1,&stu.score2);无无&#i

28、nclude#defineFORMAT%dn%sn%fn%fn%fnstructstudent/*定义为外部结构体类型定义为外部结构体类型*/intnum;charname20;floatscore3;stu=12345,LiLi,67.5,89,78.6;voidmain()voidprint(structstudent*);/*形参指向结构体的指针变量形参指向结构体的指针变量*/print(&stu);/*实参为实参为stu的起始地址的起始地址*/voidprint(structstudent*p)printf(FORMAT,pnum,pname,pscore0,pscore1,pscor

29、e2);/*用指针变量调用成员之值用指针变量调用成员之值*/printf(“n”);例例11.6例例11.5改为用改为用结构体变量的指针作实参结构体变量的指针作实参11.7 用指针处理链表用指针处理链表链表概述链表概述v数组:静态分配存储单元,容易造成内存浪费。数组:静态分配存储单元,容易造成内存浪费。v链表:是重要的数据结构,它根据需要,动态分链表:是重要的数据结构,它根据需要,动态分配内存单元配内存单元。head1249135614751021A1356B1475C1021DNULL1249v特征:头指针变量,存放链表首地址,链表中每特征:头指针变量,存放链表首地址,链表中每个元素称结点,

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

31、括的内容有两部分:成,包括的内容有两部分:u数据部分:整、实、字符、结构体等类型。数据部分:整、实、字符、结构体等类型。u指针变量:通常具有指向自身结构体类型的指针变量,此指针变量:通常具有指向自身结构体类型的指针变量,此指针变量用来存放下一结点的地址,以便一环扣一环而形指针变量用来存放下一结点的地址,以便一环扣一环而形成链表。成链表。structstudentintnum;floatscore;structstudent*next;其中:其中:next是成员名,是指针类型,是成员名,是指针类型,它指向它指向structstudent数据类型数据类型.9910189.5991039099107

32、85NULLnumscorenext简单链表简单链表#include#defineNULL0structstudentlongnum;floatscore;structstudent*next;voidmain()structstudenta,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;doprintf(“%ld%5.1fn”,pnum,pscore);p=pnext;while

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

34、点的next内容,即内容,即NULL赋给赋给p再进行判断,再进行判断,p!=NULL条件不成立,循环结束。条件不成立,循环结束。本例所有结点是在程序中定义的,不是临时开辟的,本例所有结点是在程序中定义的,不是临时开辟的,用完也不能释放,这种链表称用完也不能释放,这种链表称“静态链表静态链表”。处理动态链表所需的函数处理动态链表所需的函数为处理动态链表,为处理动态链表,C提供了开辟和释放存储单元的函数:提供了开辟和释放存储单元的函数:vmalloc函数函数l函数原型:函数原型:void*malloc(unsignedintsize);l作用:在动态区分配一个长度为作用:在动态区分配一个长度为si

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

36、dfree(void*p);l作用:释放由作用:释放由p指向的内存区,使这部分内存区能被其指向的内存区,使这部分内存区能被其它变量使用。它变量使用。P所指向的是最近一次所指向的是最近一次calloc或或malloc分配分配的存储区域。的存储区域。free函数无返回值。函数无返回值。v注:旧版本提供的注:旧版本提供的malloc和和calloc函数得到的是指函数得到的是指向字符型数据的指针。向字符型数据的指针。vANSIC提供的提供的malloc和和calloc函数规定为函数规定为void*类类型,这并不是说该函数调用后无返回值,而是返回型,这并不是说该函数调用后无返回值,而是返回一个结点的地址

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

38、据的单向动态链表。v思路:思路:设置设置3个指针变量个指针变量head、p1、p2head:指向链表头的指针变量,初始化指向链表头的指针变量,初始化head=NULL。p1:指向后继结点的首地址的指针变量指向后继结点的首地址的指针变量p2:指向结点成员指向结点成员next的指针变量。的指针变量。next的值是的值是下一个结点的首地址。下一个结点的首地址。循环方式用循环方式用malloc函数开辟第函数开辟第1个结点。个结点。n=1p1、p2指向第指向第1结点首地址(见下页插图)结点首地址(见下页插图)输入数据,如果输入数据,如果p1num!=0,则则head=p1结点链入链表,反之不链入。结点链

39、入链表,反之不链入。开辟第开辟第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.59910390(c)(n=2)重复重复两步开辟第两步开辟第3个结点,并链入链表。个结点,并链入链表。9910189.59910

40、390headp2p19910785(a)n=39910189.59910390headp2p19910785(b)n=3n=n+1n=1head=p1p2next=p1真真假假(把把p1所指结点作所指结点作为第一个结点为第一个结点)(把把p1所指结点所指结点连接到表尾连接到表尾)p2=p1(p2移到表尾)移到表尾)再开辟一个新结点,使再开辟一个新结点,使p1指向它指向它读入一个学生数据给读入一个学生数据给p1所指结点所指结点表尾结点的指针变量置表尾结点的指针变量置NULL开辟一个新结点,并使开辟一个新结点,并使p1,p2指向它指向它读入一个学生数据给读入一个学生数据给p1所指向的结点所指向的

41、结点head=NULL,n=0当读入的当读入的p1num不是零不是零再开辟新结点,由于再开辟新结点,由于num数据为数据为0,退出循环。,退出循环。并使并使p2next=NULL,虽然虽然p1指向新结点但没有指向新结点但没有链入链表。链入链表。9910189.59910390p2p19910785(a)n=3head00009910189.59910390p2p19910785NULL(b)n=3head#include“stdio.h”#include“malloc.h”#defineNULL0#defineLENsizeof(structstudent)structstudentlongn

42、um;floatscore;structstudent*next;intn;structstudent*creat(void)structstudent*head;structstudent*p1,*p2;n=0;p1=p2=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&p1num,&p1score);head=NULL;while(p1num!=0)n=n+1;if(n=1)head=p1;elsep2next=p1;p2=p1;p1=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&p1num,&p1score

43、);p2next=NULL;return(head);#include“stdio.h”/*改进后改进后*/#include“stdlib.h”#defineNULL0#defineLENsizeof(structstudent)structstudentlongnum;floatscore;structstudent*next;intn;structstudent*creat(void)structstudent*head;structstudent*p1,*p2;flots;n=0;p1=p2=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&p1nu

44、m,&s);p1score=s;head=NULL;while(p1num!=0)n=n+1;if(n=1)head=p1;elsep2next=p1;p2=p1;p1=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&p1num,&s);p1score=s;p2next=NULL;return(head);输出链表输出链表思路:思路:设一个指针变量设一个指针变量p,找到链表第找到链表第1个结点的地址个结点的地址(head的值),的值),p指向该结点,输出结点各成员的数指向该结点,输出结点各成员的数据,再据,再p后移后移指向下一结点。指向下一结点。NULL

45、headPPP=head,使使p指向第一个结点指向第一个结点P指向的不是尾结点指向的不是尾结点真真假假输出输出p所指向的结点所指向的结点p=pnext当当p指的不是表尾指的不是表尾例例11.9写一个输出写一个输出链表的链表的函数函数print。voidprint(structstudent*head)structstudent*p;printf(“nNow,these%drecordsare:n”,n);p=head;if(head)!=NULL)doprintf(“%ld,%5.2fn”,pnum,pscore);p=pnext;while(p!=NULL);n n从例从例11.811.8程

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

47、101headp19910399107NULL(a)初始状初始状态态p2(b)下移一个结点下移一个结点headp199107NULL9910199103p2=p1找到要删除的结点后:找到要删除的结点后:如果要删除的是第如果要删除的是第1结点,则结点,则head=p1next。head指向第二结点,第一结点脱离。指向第二结点,第一结点脱离。head=p1nextheadp1(c)选中第一个结选中第一个结点点9910199107NULL99103如果要删除的不是第如果要删除的不是第1结点,则结点,则p2next=p1next。P1指向的结点脱离。指向的结点脱离。还要考虑链表为空和链表中没有要删除的

48、结点的情况。还要考虑链表为空和链表中没有要删除的结点的情况。headp2p1p2next=p1next(d)第二个结点被删除第二个结点被删除99107NULL9910199103p1是要删除的结点是要删除的结点是是否否链表是一个空表链表是一个空表真真假假输出输出空表空表p1=head当当nump1num以及以及p1所指的结点不是表尾结点所指的结点不是表尾结点p2=p1(p2后移一个位置)后移一个位置)p1=p1next(p1后移一个位置)后移一个位置)输出输出“找不找不到到”的信息的信息P1所指是头结点所指是头结点是是否否head=p1next(删除头结点)删除头结点)p2next=p1nex

49、t(删除一个结点)删除一个结点)structstudent*del(structstudent*head,longnum)structstudent*p1,*p2;if(head=NULL)printf(“nlistnull!n”);gotoend;p1=head;while(num!=p1num&p1next!=NULL)p2=p1;p1=p1next;if(num=p1num)if(p1=head)head=p1next;elsep2next=p1next;printf(“delete:%dn”,num);n=n-1;elseprintf(“%ldnotbeenfound!n”,num);

50、return(head);对链表的插入操作对链表的插入操作v假设结点按成员的学号从小到大排列,按排序顺假设结点按成员的学号从小到大排列,按排序顺序插入结点。序插入结点。思路:思路:找到插入点后,将该点的找到插入点后,将该点的next值指向新结点,并使新值指向新结点,并使新结点的结点的next值等于断点后面结点的首地址。值等于断点后面结点的首地址。设置设置p0、p1、p2三个指针变量。创建一个新结点,三个指针变量。创建一个新结点,p0指向其起始位置地址。指向其起始位置地址。p1指向第指向第1个结点。个结点。head991019910399107NULL99102p0p1(a)准备将准备将p0插入

51、链表插入链表中中如果如果p0num大于大于p1num,则,则p2=p1,然后然后p1后移后移一个结点。直至一个结点。直至p0num小于或等于小于或等于p1num。这时这时p0所指结点插在所指结点插在p1所指结点之前。所指结点之前。head991019910399107NULL99102p0p1p2(b)插入点位于链表中插入点位于链表中间间p0nump1nump2=p1,p1=p1next如果插入点在链表中间,则如果插入点在链表中间,则p2next=p0,p0next=p1,新结点插入了链表。新结点插入了链表。9910399107NULLp1head9910199102p0p2(c)链接新结点链

52、接新结点p0nump1nump2next=p0,p0next=p1如果插入点位于最前面,则如果插入点位于最前面,则head=p0,p0next=p1。99107NULLhead991009910399101p0p1(d)结点插在表首结点插在表首p0nump1numhead=p0,p0next=p1如果插入点位于最后面,如果插入点位于最后面,则则p1不再后移不再后移,p1next=p0,p0next=NULLp199101991079910399109NULLp0(e)结点插在表结点插在表尾尾p1next=p0p0next=NULLheadv将一个结点插入到链表中将一个结点插入到链表中算法:算法

53、:p1=head,p0=stud 原来的链表是空表原来的链表是空表是是否否当当p0nump1num以及以及p1所指的不是表尾结点所指的不是表尾结点p2=p1p1=p1next p0nump1num真真假假 P0指向头结点指向头结点是是否否head=p0p0next=p1(插到表头之前插到表头之前)p2next=p0p0next=p1(插到表中间插到表中间)p1next=p0p0next=NULL(插到表尾之后插到表尾之后)将将p0所所指的结指的结点作为点作为唯一结唯一结点点n=n+1structstudent*insert(structstudent*head,structstudent*st

54、ud)structstudent*p0,*p1,*p2;p1=head;/*使使p1指向第一个结点指向第一个结点*/p0=stud;/*p0指向要插入的结点指向要插入的结点*/if(head=NULL)/*原来的链表是空表原来的链表是空表*/head=p0;p0next=NULL;/*使使p0指向的结点作为头结点指向的结点作为头结点*/elsewhile(p0nump1num)&(p1next!=NULL)p2=p1;/*使使p2指向刚才指向刚才p1指向的结点指向的结点*/p1=p1next;/*p1后移一个结点后移一个结点*/if(p0num=p1num)if(head=p1)head=p0

55、;/*插到原来第一个结点之前插到原来第一个结点之前*/elsep2next=p0;/*插到插到p2指向的结点之后指向的结点之后*/p0next=p1;elsep1next=p0;p0next=NULL;/*插到最后的结点之后插到最后的结点之后*/n=n+1;/*结点数加结点数加1*/return(head);对链表的综合操作对链表的综合操作v用用main函数作主调函数,调用前述建立、输出、函数作主调函数,调用前述建立、输出、删除、插入结点的函数。删除、插入结点的函数。voidmain()structstudent*head,*stu;longdel_num;printf(“inputrecor

56、ds:n”);head=creat();/*建立链表,返回头指针建立链表,返回头指针*/print(head);/*输出全部结点输出全部结点*/printf(“ninputdeletenumber:”);scanf(“%ld”,&del_num);/*输入要删除的学号输入要删除的学号*/while(del_num!=0)head=del(head,del_num);/*删除后链表的头地址删除后链表的头地址*/print(head);/*输出全部结点输出全部结点*/printf(“inputthedeletenumber:”);scanf(“%ld”,&del_num);/*输入要删除的学号输入

57、要删除的学号*/printf(“ninputtheinsertedrecord:”);stu=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&stunum,&stuscore);/*输入要插入的结点输入要插入的结点*/while(stunum!=0)head=insert(head,stu);/*插入新结点,返回地址插入新结点,返回地址*/print(head);/*输出全部结点输出全部结点*/printf(“inputtheinsertedrecord:”);stu=(structstudent*)malloc(LEN);scanf(“%ld,%f”,&stunum,&stuscore);

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号