1、1,第六章 结构体与线性链表,2,6.1 用typedef定义类型,可对已有类型自行定义类型名,以作为原类型的别名。 一般形式: typedef 原类型 定义类型名; 例1 typedef int INTEGER; typedef float REAL; typedef char CHARACTER; typedef int ARRAY1010; typedef char * POINTER;,3,例2 承例1INTEGER i,j;REAL r,s,t;CHARACTER ch;ARRAY10 a,b,c,d;POINTER pa,pb; 等价于int i,j;float r,s,t;cha
2、r ch;int a10,b10,c10,d10;char *pa,*pb;,4,6.2 结构体变量说明与赋值操作,6.2.1 结构体变量说明 一般形式:struct 结构体名成员表 ;成员表可表示为类型1 结构成员名表1;类型2 结构成员名表2; 类型n 结构成员名表n;,5,例3 定义学生成绩档案 struct studentchar class110; / 班级 int number; / 学号 char name15; / 姓名 char sex; / 性别 int age; / 年龄 int scores3; / 3门课考试成绩 float average; / 平均成绩 ;,6,6
3、.2.2 结构体变量的初始化 例9struct complexfloat re,im;struct complex z1=2.0,7.0,z2=2.0,7.0; struct date int month,day,year;struct date sf=1,24,2001;,7,6.2.3 结构体变量的赋值操作引用结构体变量成员的一般形式:结构体变量.成员名 注意:同类型结构体变量可整赋值。 例 #include#includeusing namespace std;struct student char class110;int number;char name15;char sex;int
4、 age;int scores3;float average; stu1;,8,void main() int i,sum=0;strcpy(stu1.class1,“01-711“);stu1.number=10;strcpy(stu1.name,“Zhang Hua“);stu1.sex=f; stu1.age=17;for (i=0;istu1.scoresi;sum+=stu1.scoresi; stu1.average=(float)sum/3;,9,6.2.4 结构体类型的嵌套 例14 struct date int month,day,year;struct student ch
5、ar class110;int number;char name15;char sex;int age;struct date birthday; int scores3;float average;stu1=“01-711“,10,“Zhang Hua“,f,17,10,1,1984,88,79,65,0.0;,stu1. birthday.month,10,6.3 结构体数组和结构体指针,6.3.1 结构体数组 例15struct studentsint num;char name20;char sex;float score;struct students stu5;,11,例 stru
6、ct examint m35;float f;char s20; y4;y2.m14表示访问结构体变量y2中整型二维数组成员m中的数组元素m14。,12,6.3.2 结构体指针 例17 struct studentsint num;char name20;char sex;float score; struct students stu1,*ps1; struct students stu5,*ps; ps1=,13,例 struct studentsint num;char name20;char sex; float score; struct students stu1,*ps1=,14
7、,引用结构体成员的两个运算符:”.”和”-” 形式一结构体变量.成员名形式二(*结构体指针变量).成员名形式三结构体指针变量-成员名,对结构体成员的引用,15,例 承上例,可写(*ps1).num 等价于stu1.num (*ps1).name 等价于stu1.name(*ps1).sex 等价于stu1.sex(*ps1).score 等价于stu1.scoreps1- num 等价于stu1.numps1- name 等价于stu1.nameps1- sex 等价于stu1.sexps1- score 等价于stu1.score,16,6.3.3 结构体指针作为函数参数例21 承例20,用
8、以结构体指针作为函数参数 #include struct students int num;char name20;char sex;float score; ;,17,struct students stu5=101,“Li Ping“,m,55,102,“Zhang Hua“,f,72.5,103,“He Fang“,f,92.5,104,“Cheng Ling“,f,58,105,“Wang Zhiming“,m,87 ;,18,void table(struct students *ps) for (;psnumnamesexscoreendl; ,19,void ave(struct
9、 students *ps) int count=0;float sco,sum=0.0;for (;psscore; sum+=sco;if (sco60) count+; cout“Total=“sumendl;cout“average=“sum/5endl;cout“Fail to pass:“countendl; ,20,void main() struct students *ps;ps=stu;cout“No. Name Sex Scoren“;table(ps); ps=stu; ave(ps); ,21,6.4 动态存储分配及释放,6.4.1 动态数据结构静态数据结构:编译分配
10、固定内存单元,始终存在动态数据结构:运行期间动态地分配及回收内存单元动态变量需要依赖于指向它的指针变量来访问及引用,22,6.4.3 运算符new和delete使用运算符new可为动态数据申请分配堆内存。而使用运算符delete可以释放原先由new所申请的堆内存。例23 承例22,用new和delete实现相同功能。 #include#include#include,23,void main( ) struct students int num;char name15;char sex;float score; ;students *ps;ps=new students;ps-num=102;
11、strcpy(ps-name,“Zhang Hua“);,24,ps-sex=f;ps-score=72.5;coutnumnamesexscoreendl;delete ps; ,运行示例 number:102 name:Zhang Hua sex:f score:72.5,25,6.5 线性链表概念,6.5.1 自引用结构体包含一个指针成员,该指针指向与自身同一类型的结构体。 例 struct item int num;struct item *next; /链指针 ;,26,6.5.2 线性链表用链指针链在一起的自引用结构的线性集合。 例:,27,单向链表(以正向链表为例)双向链表循环链
12、表(以单向循环链表为例),head,head,head,28,对链表的主要操作有以下几种 建立或生成一个链表 查找链表元素 插入一个链表新表元素 删除一个链表元素 遍历链表,输出各表元素有关信息。,29,插表头将每一新元素固定插入至当前已生成链表的表头位置 插表尾将每一新元素固定插入至当前已生成链表的表尾位置 有序表将每一新元素插入至链表中适当位置 (表头、表中或表尾),以保持链表的有序性,30,6.6 线性链表生成与遍历,6.6.1 线性链表生成插表头例25 键入简化的学生数据,把它们组成线性链表,并输出各学生信息。要求每一新表元素都插入至已生成链表的表头位置。编写程序实现之。,31,分析:
13、 第一阶段:生成依次键入学号(假设互不相同),创建新的表元素,并插入至表头位置。遇结束标志即止,此时已生成所需链表。 第二阶段:遍历从表头开始,”顺藤摸瓜”遍历所有表元素并输出各表元素中的有关信息学号,直至表尾。程序要点:设置两个指针变量:head和temp。,32,#include#include void main( ) struct item int num; item *next; ; item *head=NULL,*temp;/初始表头为NULL int stno; coutstno;,33,while(stno!=-1) temp=new item; temp-num=stno;
14、temp-next=head; /初始表尾为NULL /以后实现表元素的连接 head=temp; /更新表头 cinstno; coutnum;temp=temp-next; coutendl; ,34,head,2,temp,NULL,2,temp,NULL,head=NULL;,temp= new item; temp-num=stno;,temp-next=head; /表尾初始化为NULL,2,head,NULL,head=temp; / 更新表头,35,5,temp,5,temp,temp= new item; temp-num=stno;,temp-next=head; / 实现
15、表元素的连接,2,head,NULL,head=temp; / 更新表头,2,head,NULL,5,2,head,NULL,temp,36,执行完第一阶段后所生成的线性链表及指针变量位置:(设输入2 5 4 1 -1),Enter students numbers,-1 to stop:2 5 4 1 -1 The output will be: 1 4 5 2,运行示例,.,1,.,4,.,5,NULL,2,head,temp,37,例26 编写插表尾的链表生成及遍历程序。 分析 第一阶段:生成依次键入学号(假设互不相同),创建新的表元素,并插入至表尾位置。遇结束标志即止,此时已生成所需链
16、表。 第二阶段:遍历从表头开始,”顺藤摸瓜”遍历所有元素并输出各表元素中的有关信息学号,直至表尾。 程序要点:设置三个指针变量:head、temp、tail。,6.6.2 线性链表生成插表尾,38,#include #include void main( ) struct item int num;item *next; ; item *head=NULL,*temp,*tail; /初始表头为NULL int stno; coutstno;,39,while(stno!=-1) temp=new item; temp-num=stno; temp-next=NULL; if(head=NUL
17、L) / list is empty head=temp; tail=temp; else / list is not empty tail-next=temp;tail=temp; cinstno; ,40,coutnum; temp=temp-next; coutendl; ,41,head,2,temp,NULL,2,tail,NULL,head=NULL;,temp= new item;temp-num=stno;temp-next=NULL;,if (head=NULL) / 空表 head=temp;tail=temp;,NULL,head,42,43,执行完第一阶段后所生成的线性
18、链表及指针变量位置:,.,2,.,5,.,4,NULL,1,head,temp,tail,运行示例: Enter students numbers,-1to stop:2 4 5 1 -1 The output will be:2 4 5 1,44,设输入 2 5 4 1 -1 线性链表生成插表头,LIFO与FIFO (后进先出(先进后出)与先进先出),LIFO:Last In First Out 栈、堆,.,1,.,4,.,5,NULL,2,head,45,FIFO: First In First Out 队列,.,2,.,5,.,4,NULL,1,head,线性链表生成插表尾,46,6.7
19、 在已知线性链表中的插入与删除操作,更 新,查 找,检 索,插 入,删 除,修 改,47,插入前,插入操作准备,.,2,.,5,.,4,NULL,1,head,(1)设insno=3,tono=4。欲将表元素3插入至链表中表元素之后。,head,top,insp,48,执行后插入操作,插入后,.,2,.,5,.,4,NULL,1,head,top,.,3,insp,.,2,.,5,.,4,NULL,1,head,.,3,insp-next=top-next;,top-next=insp;,1,2,49,例27 下述函数定义实现将一学号为insno的新表元素插入至已知链表中学号为tono的表元素
20、之后。 (头指针不变,函数无需返回头指针) void insertafter(item *head,int insno,int tono) item *insp,*top;insp= new item;insp-num=insno;top=head;while (top-num!=tono)top=top-next;insp-next=top-next; / 插入 top-next=insp; ,50,两个新问题 a. 如何找到链表中所指定被插入表元素的前趋表元素的指针位置?,3,insp,.,2,.,5,.,4,NULL,1,head,top,(2)设将表元素3插入至链表中表元素之前。,pr
21、ep,51,b. 怎样处理欲插入至链表中的表头元素之前?(设将表元素3插入至链表中表元素2之前),.,2,.,5,.,4,NULL,1,head,3,insp,top,?,52,解决办法:if (top=head) / 问题2 插表头 else / 问题1 插表中用指针prep从表头开始搜索,直到它指向top所指表元素的前趋表元素位置,再作插入操作,53,a.将表元素3插入至链表中表头元素2之前 插入操作准备,执行插入操作,.,2,.,5,.,4,NULL,1,head,3,insp,.,2,.,5,.,4,NULL,1,head,.,3,insp-next=top; head=insp;,t
22、op,top,54,b.将表元素3插入至链表中表元素4之前 插入操作准备,执行插入操作,top,(2),.,2,.,5,.,4,NULL,1,head,3,insp,(1),prep,(3),top,prep,.,2,.,5,.,4,NULL,1,head,.,3,insp-next=top; prep-next=insp;,prep-next = = top,55,例28 下述函数定义实现将一个学号为insno的新表元素插入至已知链表中学号为tono的表元素之前。 (头指针可能变化,函数需返回头指针)item *insertbefore(item *head,int insno,int to
23、no) item *insp,*top,*prep;insp= new item;insp-num=insno;top=head;while (top-num!=tono)top=top-next;if (top=head) / 插表头 insp-next=top;head=insp; ,56,else / 插表中 prep=head;while (prep-next!=top)prep=prep-next;insp-next=top;prep-next=insp;return (head); ,57,将链表中的表元素2即表头元素删除,生成新链表序列5、4、1。此时应注意新链表的表头指针已有改
24、变。,.,2,.,5,.,4,NULL,1,head,.,2,.,5,.,4,NULL,1,head,delp,delp,head=delp-next;,prep-next=delp-next;,prep,(3) 在已知线性链表中删除以delno为学号的那一表元素。,58,item *delete(item *head,int delno) item *delp,*prep;delp=head;while (delp-num!=delno)delp=delp-next;if (delp=head) / 删表头元素 head=delp-next;else / 删非表头元素 prep=head;while (prep-next!=delp)prep=prep-next;prep-next=delp-next; / 删除一个元素delete delp; /回收空间return (head); ,例30 在已知线性链表中删除以delno为学号的那一表元素。,