第八章 结构和联合类型

109
第第第 第第第第第第第 第第第第第第第第第 第第第第第第第第第 第第 第第第 [email protected] 第: C 第第第第第第

Upload: tavita

Post on 14-Jan-2016

147 views

Category:

Documents


0 download

DESCRIPTION

第八章 结构和联合类型. 教 材 : C 程序设计导论. 主讲:谭成予 [email protected]. 武汉大学计算机学院. 结构类型定义与引用. 结构类型和指针. 结构数组. 链表. 联合类型. 本讲重点. 结构类型. 结构类型是 一种 构造数据类型 用途:把 不同类型 的数据组合成一个整体------- 自定义数据类型. 合法标识符 可省 : 无名结构类型. struct [ 结构名 ] { 类型标识符 成员名; 类型标识符 成员名; ……………. } ;. 成员类型可以是 基本型或构造型 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第八章  结构和联合类型

第八章 结构和联合类型第八章 结构和联合类型

武汉大学计算机学院武汉大学计算机学院武汉大学计算机学院武汉大学计算机学院

主讲:谭成予[email protected]

教 材 : C 程序设计导论

Page 2: 第八章  结构和联合类型

结构类型定义与引用

结构类型和指针

结构数组

链表

联合类型

本讲重点本讲重点

Page 3: 第八章  结构和联合类型

结构类型是一种构造数据类型 用途:把不同类型的数据组合成一个整体 ------- 自定义数

据类型

struct [ 结构名 ]{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;

成员类型可以是基本型或构造型( 数组、指针或其他结构类型)

struct 是关键字 ,不能省略

合法标识符可省 : 无名结构类型

结构类型

Page 4: 第八章  结构和联合类型

例 struct student { long int order; char name[20]; char sex; short int age; int score[10]; char addr[30]; };

结构类型定义描述结构的组织形式 , 不分配内存

结构类型定义的作用域

name

order

sex

age

score

addr

4 字节

2 字节

20 字节1 字节

20 字节

30 字节

……

..…

..

结构类型

Page 5: 第八章  结构和联合类型

例 struct id_card { char name[30]; char sex; char nationality[20];

struct date {

int year,month,day; }birthday; char *p_addr; struct date signed_date;

long number; char *office;};

同一结构类型各成员不能同名 ,不同结构类型成员可以同名

结构类型可以嵌套定义

结构类型

Page 6: 第八章  结构和联合类型

例 struct wrong { char name[30]; int count; struct wrong a; };

×结构类型不能递归定义

结构类型

Page 7: 第八章  结构和联合类型

一般形式:struct 结构名{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;struct 结构名 变量名表列;

结构变量的定义先定义结构类型,再定义结构变量

Page 8: 第八章  结构和联合类型

例 struct student { long int order; char name[20]; char sex; short int age; int score[10]; char addr[30]; }; struct student stu1,stu2;

/*struct coord 表示屏幕上一个点的坐标 */

例 struct coord{ float x;

float y;};

struct coord first,second;

结构变量的定义

Page 9: 第八章  结构和联合类型

例 #define STUDENT struct student STUDENT { long int order; char name[20]; char sex; short int age; int score[10]; char addr[30]; }; STUDENT stu1,stu2;

结构变量的定义

Page 10: 第八章  结构和联合类型

struct 结构名{ 类型标识符 成员名; 类型标识符 成员名; …………….} 变量名表列;

一般形式:

定义结构类型的同时定义结构变量

结构变量的定义

Page 11: 第八章  结构和联合类型

例 struct student { long int order; char name[20]; char sex; short int age; int score[10]; char addr[30]; }stu1,stu2;

例 struct coord{ float x;

float y;}first,second;

/*struct coord 表示屏幕上一个点的坐标 */

结构变量的定义

Page 12: 第八章  结构和联合类型

struct{ 类型标识符 成员名; 类型标识符 成员名; …………….} 变量名表列;

用无名结构类型直接定义变量只能一次

一般形式:

直接定义结构类型变量

结构变量的定义

Page 13: 第八章  结构和联合类型

例 struct { long int order; char name[20]; char sex; short int age; int score[10]; char addr[30]; }stu1,stu2;

例 struct { float x;

float y;}first,second;

/*struct coord 表示屏幕上一个点的坐标 */

结构变量的定义

Page 14: 第八章  结构和联合类型

– 说明• 结构类型与结构类型变量概念不同

– 类型 : 不分配内存; 变量 : 分配内存– 类型 : 不能赋值、存取、运算 ; 变量 : 可以

• 结构类型可嵌套• 结构类型成员名与程序中变量名可相同,不会混淆• 结构类型及变量的作用域与生存期

结构变量的定义

Page 15: 第八章  结构和联合类型

例 struct date { int month; int day; int year; }; struct student { int num; char name[20]; struct date birthday; }stu;

num namebirthday

month day year

结构变量的定义

Page 16: 第八章  结构和联合类型

例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu;

num namebirthday

month day year

结构变量的定义

Page 17: 第八章  结构和联合类型

结构类型变量的引用

引用规则• 结构类型变量不能整体引用 , 只能引用变量成员

引用方式:结构类型变量名 . 成员名•可以将一个结构类型变量赋值给另一个结构类型变量•结构类型嵌套时逐级引用

Page 18: 第八章  结构和联合类型

例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;

stu1.num=10;

stu1.score=85.5;

stu1.score+=stu2.score; stu1.age++;

成员 ( 分量 ) 运算符优先级 : 1结合性 : 从左向右

结构类型变量不能整体引用 , 只能引用变量成员

引用方式: 结构类型变量名 . 成员名

结构类型变量的引用

Page 19: 第八章  结构和联合类型

例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;

printf(“%d,%s,%c,%d,%f,%s\n”,stu1); ()

stu1={101,“Wan Lin”,‘M’,19,87.5,“DaLian”}; ()

结构类型变量的引用

不能整体引用

Page 20: 第八章  结构和联合类型

例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;

if(stu1==stu2)…….. ()

结构类型变量的引用

不能整体引用

Page 21: 第八章  结构和联合类型

结构类型嵌套时逐级引用例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;

stu2=stu1; ( )

结构类型变量的引用

Page 22: 第八章  结构和联合类型

例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu1,stu2;

num namebirthday

month day year

stu1.birthday.month=12;

结构类型嵌套时逐级引用

结构类型变量的引用

Page 23: 第八章  结构和联合类型

/*L8-1.C: 计算某个同学 5 门课程成绩的平均分。 */#include <stdio.h>int main(void){ struct student{

char *name; /* 姓名 */long order; /* 学号 */int score[5]; /* 成绩 */float average; /* 平均分 */}who;int sum=0,n;printf(“input name,order and 5 scores\n”);scanf(“%s%ld”,who.name,&who.order);

char name[20];

Page 24: 第八章  结构和联合类型

for(n=0;n<5;n++)scanf(“%d”,&who.score[n]);

who.average=0.0;for(n=0;n<5;n++)

sum+=who.score[n];who.average=(float)sum/5;

printf(“\nname=%s\torder=%ld\n”,who.name.who.order); printf(“average=%f\n”,who.average); return 0;}

Page 25: 第八章  结构和联合类型

/*L8-2.C: 输入矩形左上角和右下角坐标,计算该矩形长和宽及面积。*/#include <stdio.h>#include <math.h>int main(void){ float length,width,area; struct coord{

float x,y; }; struct rectangle{ struct coord topleft,bottomrt ; }mybox; printf(“enter the top left x,y coordinate:\n”); scanf(“%f%f”,&mybox.topleft.x,&mybox.topleft.y); printf(“enter the bottom right x,y coordinate:\n”); scanf(“%f%f”,&mybox.bottomrt.x,&mybox.bottomrt.y); length=fabs((double)(mybox.bottomrt.x-bybox.topleft.x)); width=fabs((double)(mybox.topleft.y-mybox.bottomrt.y)); area=length*width; printf(“\nlength=%f\twidth=%f\n”,length,width); printf(“area=%f\n”,area); return 0; }

Page 26: 第八章  结构和联合类型

struct 结构类型名{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;struct 结构类型名 结构类型变量 ={ 初始数据 } ;

形式一:

结构变量的初始化

Page 27: 第八章  结构和联合类型

例 struct student { int num; char name[20]; char sex; int age; char addr[30]; }; struct student stu1={112,“Wang Lin”,‘M’,19, “200 Beijing Road”};

结构变量的初始化

Page 28: 第八章  结构和联合类型

例 struct student { char name[20]; long order; int score[5]; float average; }; struct student who={“Wang Lin”,031112,{92,91,89,87,94},0.0};

结构变量的初始化

Page 29: 第八章  结构和联合类型

例 struct coord { float x,y;}; struct rectangle{

struct coord topleft;struct coord bottomrt;

}; struct rectangle mybox={{1.8,8.3},{12.4,1.29}};

结构变量的初始化

Page 30: 第八章  结构和联合类型

struct 结构类型名{ 类型标识符 成员名; 类型标识符 成员名; …………….} 结构类型变量 ={ 初始数据 } ;

形式二:

结构变量的初始化

Page 31: 第八章  结构和联合类型

例 struct student { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112,“Wang Lin”,‘M’,19, “200 Beijing Road”};

初值表中初值的个数 <= 结构变量长远的个数

结构变量的初始化

Page 32: 第八章  结构和联合类型

例 struct student { char name[20]; long order; int score[5]; float average; }who={“Wang Lin”,031112,{92,91,89,87,94},0.0};

例 struct coord { float x,y;}; struct rectangle{

struct coord topleft;struct coord bottomrt;

} mybox={{1.8,8.3},{12.4,1.29} };

结构变量的初始化

Page 33: 第八章  结构和联合类型

struct{ 类型标识符 成员名; 类型标识符 成员名; …………….} 结构类型变量 ={ 初始数据 } ;

形式三:

结构变量的初始化

Page 34: 第八章  结构和联合类型

例 struct { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112,“Wang Lin”,‘M’,19, “200 Beijing Road”};

结构变量的初始化

Page 35: 第八章  结构和联合类型

例 struct { char name[20]; long order; int score[5]; float average; }who={“Wang Lin”,031112,{92,91,89,87,94},0.0};

例 struct coord { float x,y;}; struct {

struct coord topleft;struct coord bottomrt;

} mybox={{1.8,8.3},{12.4,1.29}};

结构变量的初始化

Page 36: 第八章  结构和联合类型

结构类型定义与引用

结构类型和指针

结构数组

链表

联合类型

本讲重点本讲重点

Page 37: 第八章  结构和联合类型

指向结构类型变量的指针– 定义形式: struct 结构类型名 * 结构类型指针名 ;

例 struct student *p;

存放结构类型变量在内存的起始地址

struct student stu1;struct student *p=&stu1;stu1.num=101; (*p).num=101

结构类型和指针

Page 38: 第八章  结构和联合类型

num

name

sex

age

stu

pstruct student { int num; char name[20]; char sex; int age; }stu;struct student *p=&stu;

结构类型和指针

Page 39: 第八章  结构和联合类型

(* 结构类型指针名 ). 成员名 结构类型指针名 -> 成员名 结构类型变量名 . 成员名

• 使用结构类型指针变量引用成员形式

指向运算符优先级 : 1结合方向:从左向右

例 int n; int *p=&n; *p=10; n=10

结构类型和指针

Page 40: 第八章  结构和联合类型

int main(void){ struct student { long int num;

char name[20]; char sex; float score;

}stu_1,*p; p=&stu_1; stu_1.num=89101; strcpy(stu_1.name,"Li Lin"); p->sex='M'; p->score=89.5; printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n",

(*p).num,p->name,stu_1.sex,p->score); return 0;}

例 8.3 指向结构类型的指针变量

Page 41: 第八章  结构和联合类型

struct student{ int num; char name[20]; char sex; int age;}stu[3]={{10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19},

{10104,"Wang Min",'F',20}};

int main(void){ struct student *p; for(p=stu;p<stu+3;p++) printf("%d%s%c%d\n",p->num,p->name,p->sex,p->age); return 0;}

例 指向结构类型数组的指针

numnamesexage

stu[0]

p

stu[1]

stu[2]

p+1

Page 42: 第八章  结构和联合类型

/*L8-3.C: 分析下面程序的运行结果 */#include <stdio.h>int main(void){ struct {

int x;int y;

}a[2]={{1,2},{3,4}},*p=a;printf(“%d,”,++p->x);printf(%d\n”,(++p)->x);return 0;

}

p

a[0]

a[1]

p

1

2

3

4

2

2,3

结构类型和指针

Page 43: 第八章  结构和联合类型

结构类型定义与引用

结构类型和指针

结构数组

链表

联合类型

本讲重点本讲重点

Page 44: 第八章  结构和联合类型

形式一 : struct student { int num; char name[20]; char sex; int age; };struct student stu[2];

num

name

sex

age

num

name

sex

age

stu[0]

stu[1]

25B

结构数组的定义

三种形式:

Page 45: 第八章  结构和联合类型

形式二 : struct student { int num; char name[20]; char sex; int age; }stu[2];

num

name

sex

age

num

name

sex

age

stu[0]

stu[1]

25B

结构数组的定义

Page 46: 第八章  结构和联合类型

形式三 : struct { int num; char name[20]; char sex; int age; }stu[2];

num

name

sex

age

num

name

sex

age

stu[0]

stu[1]

25B

结构数组的定义

Page 47: 第八章  结构和联合类型

分行初始化 : struct student { int num; char name[20]; char sex; int age; };struct student stu[ ]={{100,“Wang Lin”,‘M’,20}, {101,“Li Gang”,‘M’,19}, {110,“Liu Yan”,‘F’,19}};

全部初始化时维数可省

结构数组初始化

Page 48: 第八章  结构和联合类型

顺序初始化 : struct student { int num; char name[20]; char sex; int age; };struct student stu[ ]={100,“Wang Lin”,‘M’,20, 101,“Li Gang”,‘M’,19, 110,“Liu Yan”,‘F’,19};

结构数组初始化

Page 49: 第八章  结构和联合类型

例 struct { int num; char name[20]; char sex; int age; }stu[ ]={{……},{……},{……}};

例 struct student { int num; char name[20]; char sex; int age; }stu[ ]={{……},{……},{……}};

结构数组初始化

Page 50: 第八章  结构和联合类型

结构数组引用引用方式: 结构数组名 [ 下标 ]. 成员名

struct student { int num; char name[20]; char sex; int age; }str[3];

stu[1].age++;

strcpy(stu[0].name,”ZhaoDa”);

Page 51: 第八章  结构和联合类型

例 8.4 统计后选人选票

struct person{ char name[20]; int count;}leader[3]={“Li”,0,“Zhang”,0,”Wang“,0}; int main(void){ int i,j; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); for(j=0;j<3;j++)

if(strcmp(leader_name,leader[j].name)==0) leader[j].count++;

} for(i=0;i<3;i++) printf("%5s:%d\n",leader[i].name,leader[i].count); return 0;}

name count

Li

Zhang

Wang

0

0

0

Page 52: 第八章  结构和联合类型

应用举例

Page 53: 第八章  结构和联合类型

例 8.5 编程,输入 10 个学生的姓名和数学、英语和语文三门功课的成绩,计算每个学生的平均成绩,并输出学生姓名和平均成绩。

#include <stdio.h>#define N 30struct student{

char name[20]; /* 学生姓名 */float math; /* 数学成绩 */float eng; /* 英语成绩 */float cuit; /* 语文成绩 */float aver; /* 平均成绩 */

};

Page 54: 第八章  结构和联合类型

int main( void){ struct student s[N];

int i;for(i=0;i<N;i++){ printf(“ 请输入第 %d 学生的数据 \n”,i+1);

printf(“ 姓名:” );gets(s[i].name);printf(“ 数学、英语、语文成绩:” );scanf(“%f,%f,%f ”,&s[i].math,&s[i].eng,&s[i].cuit);

s[i].aver=(s[i].math+s[i].eng+s[i].cuit)/3.0;}printf(“ 姓名 平均成绩 \n”);for(i=0;i<N;i++)

printf(“%s%6.1f\n”,s[i].name,s[i].aver); return 0;}

Page 55: 第八章  结构和联合类型

例 8.6 输入 N 个整数,记录输入的数和序号,按从小到大的顺序排列(如果两个整数相同,按输入的先后次序排列)。输出排序以后的每个整数和它原来的序号。#include <stdio.h>#define N 10struct data{

int no;int num;

};int main(void ){ struct data x[N],temp;

int i,j;/* 输入 10 个整数 */printf(“ 输入 10 个整数:” );for(i=0;i<N;i++){ scanf(“%d”,&x[i].num);

x[i].no=i+1;}

Page 56: 第八章  结构和联合类型

int main( void){ struct student s[N];

int i;for(i=0;i<N;i++){ printf(“ 请输入第 %d 学生的数据 \n”,i+1);

printf(“ 姓名:” );gets(s[i].name);printf(“ 数学、英语、语文成绩:” );scanf(“%f,%f,%f ”,&s[i].math,&s[i].eng,&s[i].cuit);

s[i].aver=(s[i].math+s[i].eng+s[i].cuit)/3.0;}printf(“ 姓名 平均成绩 \n”);for(i=0;i<N;i++)

printf(“%s%6.1f\n”,s[i].name,s[i].aver); return 0;}

Page 57: 第八章  结构和联合类型

例 8.7, 问题描述: n 个小孩围成一圈,依次编号。老师指定从第 w 个小孩开始报数,报数为 s 的小孩出列;然后从下一个小孩开始重新报数,重复上述过程,直到所有小孩都出列。

分析:数据结构,如何表示队列和小孩? 每个小孩用一个结构类型表示: struct child{ int ino; /* 当前小孩编号 */ int next; }; /* 下一个小孩编号 */ n 个小孩组成队列用结构数组表示: struct child link[N+1]; /* 下标为 0 的元素不使用 */ N 为可以容纳的人数上限

约瑟夫问题

Page 58: 第八章  结构和联合类型

分析:算法: ( 1 )初始化队列 link: link[k].nextk+1 k=1,……,n-1 link[n].next1 ( 2 )开始报数 if(link[k].ino!=0) 如果第 k 个小孩在队列中 I+1I 报数变量 I 加 1 ( 3 )如果 I >=s ,则第 k 个人出列,转( 5 ),否则转( 4 ) ( 4 ) k 更新为下一个小孩编号 klink[k].next, 转( 2 ) ( 5 )输出第 k 个小孩编号 link[k].ino ( 6 ) link[k].ino0 表示已经出列 ( 7 )已经出列人数加 1count ( 8 ) 如果 count 等于总人数 n ,则转( 9 ) ,否则转( 2 ) ( 9 )算法结束

约瑟夫问题

Page 59: 第八章  结构和联合类型

#include <stdio.h>#define N 100 /* 程序能够处理的人数上限 */int main(){ struct child{ int ino,next;}link[N+1]; int I,n_child,which,com_out,k,count;

/* 输入已知数据:小孩实际人数、初始报数小孩编号、出列的编号 */ scanf(“%d%d%d”,&n_child,&which,&come_out);

if(n_child>N) printf(“too many to hold\n”);

else {/* 初始化队列 */ for(I=1;I<=n_child;I++)

{ if(I==n_child) link[I].next=1; else link[I].next=I+1;

link[I].ino=I;}

/* 开始报数 */ k=which;/* 初始报数小孩编号 */

count=0;/* 出列人数 */

Page 60: 第八章  结构和联合类型

while(count!=n_child) { I=0;/* 报数的数值 */

while(1){ if(link[k].ino!=0) I++;

if(I>=come_out) break;k=link[k].next;

}printf(“%d\t”,link[k].ino);/* 输出出队小孩编号 */link[k].ino=0;/* 第 k 个小孩出队 */count++; /* 出队人数加 1*/if(count%10==0)

printf(“\n”); } printf(“bye!\n”); } return 0;}

Page 61: 第八章  结构和联合类型

例 8.8 编程实现两个复数的乘法运算。

分析:一个复数由实部和虚部组成,可以用含有两个浮点数类型的成员的结构类型来表示:

struct complex{ float re; /* 实部 */ float im; /* 虚部 */ }; struct complex x,y; x*y 的结果的实部为 x.re*y.re-x.im*y.im x*y 的结果的虚部为 x.re*y.im +x.im*y.re

Page 62: 第八章  结构和联合类型

#include <stdio.h>struct complex{ float re; float im;};int main( void){ struct complex x, y, z; printf(“ 请输入第 1 个复数 \n”);

printf(“ 实部:” ); scanf(“%f”,&x.re);printf(“ 虚部” ); scanf(“%f”,&x.im);printf(“ 请输入第 2 个复数 \n”);printf(“ 实部:” ); scanf(“%f”,&y.re);printf(“ 虚部” ); scanf(“%f”,&y.im);z.re=x.re*y.re - x.im*y.im;z.im=x.re*y.im + x.im*y.re;printf(“ 两个复数相乘,结果:” );if (z.im<0) printf(“%8.2f%8.2fi\n”,z.re,z.im);else printf(“%8.2f+%8.2fi\n”,z.re,z.im);return 0;

}

Page 63: 第八章  结构和联合类型

例 8.9 编程计算当前时间的下一秒的时间。

分析:时间由时、分、秒构成,采用一个结构类型来表示时间:

struct time{ int hour; /* 时 */ int minutes;   /* 分 */

int second;   /* 秒 */  };

Page 64: 第八章  结构和联合类型

#include <stdio.h>struct time{ int hour; int minutes; int second;};int main(void ){ struct time now,ntime; printf(“ 请输入当前时间,时间格式:时:分:秒 \n”); scanf(“%d:%d:%d”,&now.hour,&now.minutes,&now.second); ntime=now; ntime.second++; if (ntime.second>=60) { ntime.second=0; ntime.minutes++; if (ntime.minutes>=60) { ntime.minutes=0;

ntime.hour++; if (ntime.hour>=24) ntime.hour=0; } } printf(“ 下一秒时间: %d:%d:%d\n”,ntime.hour, ntime.minutes,

ntime.second);return 0;

}

Page 65: 第八章  结构和联合类型

结构类型定义与引用

结构类型和指针

结构数组

链表

联合类型

本讲重点本讲重点

Page 66: 第八章  结构和联合类型

引用自身的结构例如, struct tnode{

char word[20];int count;struct tnode*left;struct tnode*right;};

结构成员:指向自身所属的结构类型的对象

常用于构造各种数据结构:队列、链表、树、图等。

Page 67: 第八章  结构和联合类型

链接方式存储的线性表简称为链表( Linked List ),是常见的数据结构。

链表的具体存储表示为:  ① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)  ② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针( pointer )或链 (link) )

什么是链表?

Page 68: 第八章  结构和联合类型

┌──┬──┐│data│next│└──┴──┘   data 域 -- 存放结点值的数据域  next 域 -- 存放结点的直接后继的地址(位置)的指针域(链域)

例如:struct node{ int data; struct node *next;};

链表的结点结构

Page 69: 第八章  结构和联合类型

单链表:每个结点只有一个链域的链表。

NULL

head

head :链表的头指针

链表分类

Page 70: 第八章  结构和联合类型

head

head

循环链表

链表分类

Page 71: 第八章  结构和联合类型

双向链表:每个结点有两个链域的链表。

head

NULL

headNULL

链表分类

Page 72: 第八章  结构和联合类型

NULL

head

1 2 3

链表中结点都在程序中定义,不是临时开辟的,用完后不能释放,并且,链表中可以创建的结点数有限制。称为“静态链表”

静态链表

Page 73: 第八章  结构和联合类型

#include <stdio.h>#include <stdlib>struct node{  int data;  struct node *next;};int main(){  struct node a,b,c,*head;*p;  a.data=1;  b.data=2;  c.data=3;  head=&a;  a.next=&b;  b.next=&c;

  c.next=NULL;  p=head;  do{ printf(“%d\t”,p->data);   p=p->next;  }while(p!=NULL);  return 0;}

Page 74: 第八章  结构和联合类型

建立链表遍历链表删除链表中的结点插入结点 以单链表为例进行说明。

对链表的操作

Page 75: 第八章  结构和联合类型

结点类型: struct child{ char name[20];

struct child *next; }*new,*head,*tail;

head

newNULL

先进先出链表

(1)头指针置空head=NULL;

(2)创建新结点new=(struct child*)malloc(sizeof(struct child));new->next=NULL;

(3) 新结点连入链表 if(head==NULL){ head=new; tail=new;} else tail->next=new;重复( 2 )、( 3 )步直到链表创建完成。

建立链表 (尾插法建表)

Page 76: 第八章  结构和联合类型

建立链表 (尾插法建表)#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

struct node * creatrightlink-_1(){ struct node *head,*new,*tail; int n;

head=NULL; scanf(“%d”,&n);

while(n!=-1){ new=(struct node *)malloc(sizeof(struct node));

new->data=n;new->next=NULL;if(head==NULL)

head=new;else

tail->next=new;tail=new;scanf(“%d”,&n); }

return (head); }

Page 77: 第八章  结构和联合类型

建立链表 (尾插法建表)#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

int creatrightlink_2(struct node **phead){ struct node *new,*tail; int n,k=0;

*phead=NULL; scanf(“%d”,&n);

while(n!=-1){ new=(struct node *)malloc(sizeof(struct node));

new->data=n;new->next=NULL;if(*phead==NULL)

*phead=new;else

tail->next=new;tail=new;scanf(“%d”,&n); k++; }

return (k); }

Page 78: 第八章  结构和联合类型

(1)头指针置空head=NULL;

(2)创建新结点new=(struct child*)malloc(sizeof(struct child));

(3) 新结点连入链表 new->next=head; head=new;重复( 2 )、( 3 )步直到链表创建完成。

 

head

new

NULL

head

后进先出链表

建立链表 (头插法建表)

Page 79: 第八章  结构和联合类型

建立链表 (头插法建表)#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

struct node * creatleftlink_1(){ struct node *head,*new; int n;

head=NULL; scanf(“%d”,&n);

while(n!=-1){ new=(struct node *)malloc(sizeof(struct node));

new->data=n;new->next=head;head=new;scanf(“%d”,&n);

} return (head);

}

Page 80: 第八章  结构和联合类型

建立链表 (头插法建表)#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

int creatleftlink_2(struct node **phead){ struct node *new; int n,k=0;

*phead=NULL; scanf(“%d”,&n);

while(n!=-1){ new=(struct node *)malloc(sizeof(struct node));

new->data=n;new->next=head;*phead=new;scanf(“%d”,&n);k++;

} return (k);

}

Page 81: 第八章  结构和联合类型

(1) head=NULL;(2) 创建新结点

new=(struct child*)malloc(sizeof(struct child));(3) 找到标记结点 marker (新结点插入在标记结点的后面)(4) 新结点连入链表 new->next=marker->next; marker->next=new;;重复( 2 )、( 3 )、( 4 )步直到链表创建完成。

 

head

new

NULL

marker

在链表中间插入结点,一般用于建立有序链表

建立链表

Page 82: 第八章  结构和联合类型

 

p=head; while(p!=NULL) { puts(p->name);/* 输出当前结点数据 */

p=p->next;/*p 更新为下一个结点地址 */ }

功能:将整个链表的数据从头到尾扫描一遍

遍历链表

#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

void printlink(struct node *head){ struct node *p;

p=head;while(p!=NULL){ printf(“%d\n”,p->data;

p=p->next;}

}

Page 83: 第八章  结构和联合类型

 

( 1 )找到要删除的结点, current 指向该结点, p 指向要删除结点的前趋结点。( 2 )如果要删除的结点为头结点,则 head=current->next;( 3 )如果要删除的结点不是头结点,则 p->next=current->next( 4 )释放已经删除的结点 free(current);

NULL

head current

从链表中删除结点

Page 84: 第八章  结构和联合类型

从链表中删除结点#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;

};struct node * deletelink_1(struct node *head,int n){ struct node *p,*q;

p=head;while(p->data!=n&&p->next!=NULL){ q=p;

p=p->next; }if(p->data==n) /*找到 */{ if(p==head) /*被删除的结点是链头 */

head=p->next;else /*被删除的结点不是链头 */

q->next=p->next;free(p);

}return (head); }

Page 85: 第八章  结构和联合类型

从链表中删除结点#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;

};int deletelink_2(struct node **phead,int n){ struct node *p,*q;

p=*phead;while(p->data!=n&&p->next!=NULL){ q=p;

p=p->next; }if(p->data==n) /*找到 */{ if(p==*phead) /*被删除的结点是链头 */

*phead=p->next;else /*被删除的结点不是链头 */

q->next=p->next;free(p);return (1); }

elsereturn (0); }

Page 86: 第八章  结构和联合类型

 

向一个有序链表中插入新结点( new) 。( 1 )找到要插入结点的位置,插入在 r 指向的结点前面, p 指向的结点后面。( 2 )如果要插入在头结点前面,则

new->next=head;head=new;

( 3 )如果要插入的位置不是头结点前面,则 new->next=r;

p->next=new;

将一个结点插入一个已经存在的链表中,例如插入在链表尾部、头部或者插入在一个有序链表中。

插入结点

Page 87: 第八章  结构和联合类型

 

插入结点#include <stdio.h>#include <stdlib.h>struct node{

int data;struct node *next;};

struct node * insertsort(struct node *head, int n){ struct node *new,*p,*q; new=(struct node *)malloc(sizeof(struct node));

new->data=n; p=head;

while(p!=NULL &&p->data<n){ q=p;

p=p->next; }if(p==head){ new->next=head;

head=new; } else{ q->next=new;

new->next=p; }return (head); }

Page 88: 第八章  结构和联合类型

 

插入结点struct node * creatsortlink(struct node *head){ int n;

head=NULL; scanf(“%d”, &n);

while(n!=-1){

head=insertsort(head,n);scanf(“%d”, &n);

}return head;

}

Page 89: 第八章  结构和联合类型

结构类型定义与引用

结构类型和指针

结构数组

链表

联合类型

本讲重点本讲重点

Page 90: 第八章  结构和联合类型

构造数据类型 ,也叫共用体 用途:使几个不同类型的变量共占一段内存 ( 相互覆盖)

union 联合名{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;例 union data

{ int i; char ch; float f; }; f

ch

i 类型定义不分配内存

联合的定义

联合类型定义定义形式:

Page 91: 第八章  结构和联合类型

形式一 : union data { int i; char ch; float f; }a,b;

形式二 : union data { int i; char ch; float f; }; union data a,b,c,*p,d[3];

形式三 : union { int i; char ch; float f; }a,b,c;

联合变量的定义

Page 92: 第八章  结构和联合类型

f

ch

i

f

ch

i

a b

联合变量定义分配内存 ,长度 =最长成员所占字节数

联合变量任何时刻只有一个成员存在

联合变量的定义

Page 93: 第八章  结构和联合类型

引用方式:联合指针名 -> 成员名联合变量名 . 成员名 (* 联合指针名 ). 成员名

union data { int i; char ch; float f; }; union data a,b,c,*p,d[3];

a.i a.ch a.f

p->i p->ch p->f

(*p).i (*p).ch (*p).f

d[0].i d[0].ch d[0].f

联合变量引用

Page 94: 第八章  结构和联合类型

例 union { int i; char ch; float f; }a; a=1; ()

• 引用规则– 不能引用联合变量,只能引用其成员

联合变量引用

Page 95: 第八章  结构和联合类型

例 a.i=1; a.ch=‘a’; a.f=1.5; printf(“%d”,a.i); ( 编译通过,运行结果不对 )

联合变量引用• 引用规则

– 联合变量中起作用的成员是最后一次存放的成员

Page 96: 第八章  结构和联合类型

例 union { int i; char ch; float f; }a={1,’a’,1.5}; ()

联合变量引用• 引用规则

– 不能在定义联合变量时初始化

Page 97: 第八章  结构和联合类型

例 float x; union { int i; char ch; float f; }a,b; a.i=1; a.ch=‘a’; a.f=1.5; b=a; () x=a.f; ()

• 引用规则– 可以用一个联合变量为另一个变量赋值

联合变量引用

Page 98: 第八章  结构和联合类型

例 将一个整数按字节输出

01100001 01000001低字节高字节

01000001

01100001

ch[0]

ch[1]

i=60501ch0=101,ch1=141ch0=A,ch1=a

int main(){ union int_char { int i; char ch[2]; }x; x.i=24897; printf("i=%o\n",x.i); printf("ch0=%o,ch1=%o\n ch0=%c,ch1=%c\n",

x.ch[0],x.ch[1],x.ch[0],x.ch[1]); return 0;}

运行结果:

Page 99: 第八章  结构和联合类型

struct node{ char ch[2]; int k;}a;

union node{ char ch[2]; int k;}b;

achk

bch k

变量的各成员同时存在

任一时刻只有一个成员存在

•区别:存储方式不同•联系:两者可相互嵌套

结构类型与联合

Page 100: 第八章  结构和联合类型

例 结构类型中嵌套联合

name num sex jobclass

positionLi

Wang

1011

2086

F

M

S

T

501

prof

循环 n 次读入姓名、号码、性别、职务

job==‘s’真

真 假

读入 class读入

position输出

“输入错”

循环 n 次job==‘s’

真 假

输出 : 姓名 , 号码 ,性别 ,职业 ,班级

输出 : 姓名 , 号码 ,性别 ,职业 ,职务

job==‘t’

struct{ int num; char name[10]; char sex; char job; union { int class; char position[10]; }category;}person[2];

Page 101: 第八章  结构和联合类型

例联合中嵌套结构类型,机器字数据与字节数据的处理

00010010 00110100低字节高字节

00110100

00010010

low

high

0x1234

00010010 11111111低字节高字节

11111111

00010010

low

high

0x12ff

struct w_tag{ char low; char high;};union u_tag{ struct w_tag byte_acc; int word_acc;}u_acc;

word_accbyte_acc.low

byte_acc.high

u_acc

Page 102: 第八章  结构和联合类型

例 编程,输入一个长整型的整数,分别取出该数的各字节的值。

分析:定义一个联合类型如下所示:union data{ char s[5]; long n; };

Page 103: 第八章  结构和联合类型

例 编程,输入一个长整型的整数,分别取出该数的各字节的值。

#include <stdio.h>union data{

char s[5]; long n; };int main(void ){ union data x;

int i;printf(“ 输入一个长整数:” );scanf(“%x”,&x.n);printf(“ 各字节取值如下: \n”);

for (i=0;i<sizeof(long);i++)printf(“ 第 %d 个字节: %x”,i,x.s[i]);

printf(“\n”);return 0;

}

Page 104: 第八章  结构和联合类型

例 编程存放学生的下述信息:姓名、学号和当前住址,其中学生当前住址有两种情况:在校住宿学生用学校地址(楼房名和房间号),非在校学生用家庭住址(街道号、街道名和城市名)。并输出指定姓名学生的当前住址。

struct off_school{int strnum; /* 街道号 */char strname[20]; /* 街道名 */char city[20]; /* 城市名 */

};struct in_school{

int roomnum; /* 房间号 */ char dorm[20]; /* 楼房名 */ };union address{

struct off_school town;struct in_school gown;

};

struct student{int num; /* 学号 */char name[20]; /* 姓名 */char off_in; /* 是否在学

校住 */union address ad; /* 当前

住址 */ };

Page 105: 第八章  结构和联合类型

#include <stdio.h># include <string.h>#define N 3struct off_school{

int strnum; char strname[20]; char city[20];

};struct in_school{

int roomnum; char dorm[20]; };union address{

struct off_school town;struct in_school gown;

};

struct student{int num; char name[20]; char off_in; union address ad;

};

Page 106: 第八章  结构和联合类型

int main( void){ struct student s[N];   char name[20]; int i;

for (i=0;i<N;i++){ printf(“ 请输入第 %d 个学生数据 \n”,i+1);

printf(“ 学号:” ); scanf(“%d”,&s[i].num); printf(“ 姓名:” );

gets(s[i].name);getchar( );

Page 107: 第八章  结构和联合类型

printf(“ 是否在校住宿学生( n 在校住宿、其他表示非在校住宿):” ); s[i].off_in=getchar( );

printf(“ 请输入当前地址 \n”);i f (s[i].off_in==’n’)

   {  printf(“ 请输入房间名和房间号:” ); scanf(“%d%s”,&s[i].ad.gown..roomnum,s[i].ad.gown.dorm); }

else{ printf(“ 请输入街道号、街道名和城市名:” );

     scanf(“%d%s%s”, &s[i].ad.town.strnum,s[i].ad.town.strname, s[i].ad.town.city);

}}

Page 108: 第八章  结构和联合类型

printf(“ 输入姓名” ); gets(name); for (i=0;i<N;i++)

if (! strcmp(s[i].name, name))if (s[i].off_in==’n’){ printf(“ 姓名: %s 是在校住宿学生 \n”,s[i].name);

printf(“ 楼房名: %s  房间号 %d\n”,s[i].ad.gown.dorm,

s[i].ad.gown.roomnum); }

else{ printf(“ 姓名: %s 非在校住宿学生 \n”,s[i].name);

printf(“ 城市名: %s 楼房名: %s  房间号: %d\n”, s[i].ad.town.city,s[i].ad.town.strname,s[i].ad.tow

n.strnum);}

else printf(“ 没有这个学生” );

return 0;}

Page 109: 第八章  结构和联合类型

THE END