1 / 50

第十讲:复合数据结构 —— 数组与结构

第十讲:复合数据结构 —— 数组与结构. 北京大学 信息科学技术学院 2013 年 1 2 月. #include &lt; stdio.h &gt; int main(){ int a, b; int e; scanf (&quot;%d&quot;, &amp;a); scanf(&quot;%d&quot;, &amp;b); if(a &gt; b){ e = a; a = b; b = e; } printf(&quot;%d %d<br>&quot;, a, b); return 0; }. #include &lt; stdio.h &gt; int main(){ int a, b, c; int e;

Télécharger la présentation

第十讲:复合数据结构 —— 数组与结构

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十讲:复合数据结构——数组与结构 北京大学信息科学技术学院 2013年12月

  2. #include <stdio.h> int main(){ int a, b; int e; scanf("%d", &a); scanf("%d", &b); if(a > b){ e = a; a = b; b = e; } printf("%d %d\n", a, b); return 0; }

  3. #include <stdio.h> int main(){ int a, b, c; int e; scanf("%d", &a); scanf("%d", &b); scanf("%d", &c); if(a > b){ e = a; a = b; b = e; } if(b > c){ e = b; b = c; c = e; } if(a > b){ e = a; a = b; b = e; } printf("%d %d %d\n", a, b, c); return 0; }

  4. 如果要求: 1. 接收用户输入的10个数字 2. 输出的10个数字按照 从小到大的顺序排列 难道需要这样定义10个变量吗? int a, b, c, d, e, f, g, h, i, j; 有没有一种更简便的方式, 可以一次定义一组变量?

  5. 内容题要 • 复合数据结构 • 数组 • 结构

  6. 数组

  7. 数组是什么? 数组是一组变量 数组是 一组具有编号的变量

  8. 如何声明一个数组 必须是一个常量 int sz[10]; 数组的类型 数组名 数组中变量的数目

  9. 数组中变量的编号 int sz[10]; 0 1 2 3 4 5 6 7 8 9 数组中变量的编号 从0开始; 到数组的长度-1结束

  10. 如何访问数组中的变量 变量编号 int sz[10]; sz[0]= 1; sz[1] = 3; sz[2] = 7; … sz[8] = 16; sz[9] = 12; …sz[2]…; 数组名

  11. 数组变量赋值的一种特殊方式 • 声明时赋值 int sz[5] ={12, 3, 7, 28, -2};

  12. #include <stdio.h> int main(){ int sz[10]; int i; for(;; ){ ; } for(i = 0; i < 10; i++){ printf("%d ", sz[i]); } return 0; } 程序填空; 要求: 1.接收用户输入的10个数字 2.存放在数组sz中

  13. #include <stdio.h> int main(){ intsz[10]; inti; for( i=0 ; i < 10 ;i++){ scanf("%d", &(sz[i])); } for(i = 0; i < 10; i++){ printf("%d ", sz[i]); } return 0; }

  14. 数组的遍历 通过循环结构

  15. 正向遍历 int sz[LEN]; for(int i = 0; i < LEN; i++){ … sz[i] … }

  16. 反向遍历 int sz[LEN]; for(int i = LEN-1; i>= 0; i--){ … sz[i] … }

  17. 通过遍历实现对数组变量的控制台赋值 int sz[LEN]; for(inti= 0; i < LEN; i++){ scanf(“%d”, &(sz[i])); }

  18. 通过遍历实现对数组变量的控制台输出 int sz[LEN]; for(int i = 0; i < LEN; i++){ printf(“%d\n”, sz[i]); }

  19. 数组的应用示例 当程序要处理 一组类型相同、含义类似的数据时, 应该使用数组

  20. 游戏:过年抽奖 • 一个村庄,有128个村民 • 村长对村民说: • 今年村里出现了财政盈余M元; • M是2000-3000之间的一个整数 • 准备通过抽奖的方式把钱发给村民 • 游戏规则如下: • 每个村民上报一个在2000-3000元之间的整数 • 如果有人上报的数字和M相等,就把钱发给这些人 • 如果只有一个村民猜对,就把M元钱全部发给他 • 如果有多个人村民猜对,就把M元钱平均分配给这些村民 村长邀请我们编写一个程序, 实现村里财政盈余的自动分配

  21. 编程的基本思路 • 定义一个数组存放所有村民上报的数据 • 定义一个数组存放获奖者的编号(幸运者数组) • 定义一个整数存放获奖者人数 • 对村民从0开始编号(最后一个编号是127) • 村民按照编号顺序上报数字;程序将村民上报的数字存放在对应编号的数组变量中。 • 遍历村民上报的数字,若上报数字与幸运数相等,则 • 将村民编号添加到幸运者数组中; • 并将获奖者人数加1 • 最后,打印出获奖者编号和获得的奖金数额

  22. #define LUCKY_M 2345//财政盈余 #define POPULATION 128 //村民数量 int main( ){ int people[POPULATION]; //记录所有村民上报数字的数组 int luckyPeople[POPULATION];//幸运者数组,记录获奖者编号 int nLucky=0; //获奖者人数 int i; //循环变量 for (i=0; i<POPULATION; i++) { scanf(“%d”, &(people[i])); //读入村民报的数字,数组下标就是村民的编号 } for (i=0; i<POPULATION; i++) { if ( people[i] == LUCKY_M ) { luckyPeople[nLucky] = i; nLucky ++; } } //输出获奖者编号及所获奖金数额 for (i=0; i<nLucky; i++){ printf("%d %d\n", luckyPeople[i], LUCKY_M / nLucky); } return 0; }

  23. 回顾排序:冒泡排序 #defineLEN10 • inti,k,e,sz[LEN]; • for(i = 0; i < LEN; i++){ • scanf(“%d”, &(sz[i])); • } • for(k = 1 ; k <= LEN ; k++){ • for(i= 0; i < LEN - k; i++){ • if(sz[i] >sz[i+1]){ • e = sz[i+1]; • sz[i+1] = sz[i]; • sz[i] = e; • } • } • }

  24. 结构

  25. 结构的概念 • 通常,一个学生的个人信息,包括:学号、姓名、性别、年龄、各门功课的成绩等数据,这些数据都与一个学生相关联,类型各不相同。如果将这些数据定义为各独立的简单变量: • Number、Name、Sex、Age、Course1、Course2、… • 这样就难以反映它们之间的内在联系。应该把它们组织成一个组合项,把它们当作一个有机的整体。 • ——这个组合项就是结构(Structure)

  26. 结构类型及其定义 • 把多个紧密关联的变量(分量)顺序组织在一起,定义成一个新的复合数据类型——结构类型 • 定义一个结构类型 struct结构类型名 { 类型1 分量名1; 类型2 分量名2; ...... }; • 结构分量的类型可以相同,也可不同 • 同一个结构内的分量名不可相同 structpoint { float x; float y; };

  27. 结构类型变量的定义 • 结构类型只是定义了一种新的数据类型 • 系统并不为这个新类型分配内存空间。 • 可以使用新的结构类型来声明变量——结构类型变量。 • 结构类型变量定义的两种形式: • 用已定义的结构定义变量,例如: struct point point1; struct point point2; • 定义结构的同时定义结构类型的变量,例如: struct city{ float x, y; int population; } city1, city2; • 系统会为结构类型变量分配内存空间

  28. 结构类型变量中分量的访问 • 结构类型变量的值由其各个分量构成 • 对分量的访问一般通过“变量名.分量名”完成 • 结构赋值及访问的例子: float dx, dy; struct point { float x, y; } p1, p2, points[2]; p1.x = p1.y = 3.5f; p2.x = p2.y = 1.5f; dx = p1.x - p2.x; dy = p1.y - p2.y; • 结构变量本身可以作为一个整体来使用 points[0] = p1; points[1] = p2;

  29. struct city { char name[32]; struct city city1; }x; 结构类型中的分量 • 结构类型中分量的类型可以是任何类型 • 基本数据类型的分量 struct point{ float x, y; }; • 其他类型的分量:结构类型、数组类型 • 分量的类型不能是未定义的结构类型 • 分量的类型不能是正在定义的结构类型 • struct city { • struct point{ • float x, y; • }location; • int population; • char name[32]; • }city1; • struct city{ • struct point location; • int population; • char name[32]; • }city1; (city1.location).x

  30. 主存储器 10 20 100 200 * * 结构变量的内存布局 • 结构中各分量在内存中顺序存放 struct square { struct point { int x, y; } p1, p2; } sq1; sq1.p1.x = 10; sq1.p1.y = 20; sq1.p2.x = 100; sq1.p2.y = 200; sq1.p1.x sq1.p1.y sq1.p2.x sq1.p2.y

  31. 结构变量所占内存的大小 • 结构变量所占内存的大小并不完全等于于各分量所占字节数的总和 structchar_frequency { char c; int frequency; }; sizeof(strcutchar_frequency)通常为8,而非5 这是编译器在编译时的一个特殊要求。

  32. 结构应用示例(1)救援 • 洪水淹没了很多房子,只有屋顶还是安全的。被困的人们都爬上了屋顶。现在救生船每次都从大本营出发,到各屋顶救人,救了人之后将人送回大本营。 • 救生船每次从大本营出发,以速度50米/分钟时向下一个屋顶,达到一个屋顶后,救下其上的所有人,每人上船1分钟,船原路返回,达到大本营,每人下船0.5分钟。 • 假设大本营与任意一个屋顶的连线不穿过其它屋顶。 • 输入:第一行是屋顶数n,其后n行,每行是每个屋顶的坐标和人数 • 输出:第一行是所有人都到达大本营并登陆所用的时间,其后n行,每行是每个屋顶的坐标和人数

  33. 图中原点是大本营,每个点代表屋顶, 每个屋顶由其位置坐标和其上的人数表示。

  34. #include <stdio.h> #include <math.h> #include <malloc.h> #define MAX_ROOF_NUM 1000 #define SPEED 50.0 #define UP 1.0 #define DOWN 0.5 intmain() { introof_num; // 屋顶数. scanf("%d", &roof_num); // 输入屋顶数. struct roof { float x, y; // 屋顶坐标. intp; // 屋顶上的人数. } rfs[MAX_ROOF_NUM]; doubletotalTime = 0; // 救援总时间. inti; // 循环控制变量. //用循环处理每一个屋顶,输入屋顶位置及人数数. for (i=0; i<roof_num; i++){

  35. //用循环处理每一个屋顶,输入屋顶位置及人数.//用循环处理每一个屋顶,输入屋顶位置及人数. for (i=0; i<roof_num; i++{{ scanf("%f%f%d",&(rfs[i].x), &(rfs[i].y), &(rfs[i].p)); } // 用循环处理每一个屋顶,计算救援时间 . for (i=0; i<roof_num; i++) { // 首先计算从大本营到屋顶的双程航行时间,并累加到总救援时间中 . totalTime += 2 * sqrt(rfs[i].x*rfs[i].x + rfs[i].y*rfs[i].y) / SPEED; // 然后计算被求人员上船和下船所耗费的总时间,并累加到总救援时间中 . totalTime += rfs[i].p * (UP + DOWN); } // 打印出救援总时间. printf("Total Time is: %.2lf\n", totalTime); // 依次打印出各屋顶的位置及人数. for (i=0; i<roof_num; i++) { printf("Roof ID: %d %.2f %.2f %d\n", i+1, rfs[i].x, rfs[i].y, rfs[i].p); } return 0; }

  36. 结构应用示例(2)学生成绩统计 • 定义一个结构,包含学生的所有信息。 struct student { int number; char name[8]; char sex; int age; float course[8]; }; struct student class1[160];

  37. 单个变量、数组和结构 • 数组和结构:多个变量的集合 • 数组 • 通过数组可定义大量类型相同的变量 • 数组元素通过“变量[下标]”形式访问 • 静态数组的大小(数组元素的个数)是预先确定的,即数组定义中数组个数必须是整数常量 • 结构 • 结构把一组密切相关的变量(类型可以不同)组织成一个整体 • 结构的分量通过"变量. 分量"形式访问

  38. 单个变量、数组和结构 • 更加复杂的数据定义 • 结构中的数组 • 结构中的结构 • 结构数组

  39. 复杂结构示例:教师、学生、班级 structteacher_s { // 教师结构 char name[32]; // 姓名 char title[16]; // 职称 intage; // 年龄 }; structstudent_s { // 学生结构 char name[32]; // 姓名 char sex; // 性别 intage; // 年龄 }; structclass_s{ // 班级结构 structteacher_steacher; // 教师 structstudent_s students[180]; // 所有学生 intstudent_num; // 学生人数 };

  40. 习题

  41. 练习5:求两个正整数的最大公约数 • 接收从控制台输出的两个整数 • (假设是两个正整数) • 输出这两个数的最大公约数

  42. #include <stdio.h> intmain() { inta, b, t; scanf("%d%d", &a, &b); // a和b的最大共数也是b和a%b的最大公约数 t = a % b; while (t != 0) { a = b; b = t; t = a % b; } printf("%d\n", b); return 0; }

  43. 练习6:逆序排列数组中的元素 • 接收从控制台输出的一组整数(假设输入n个整数,n <= 100) • 按输入相反的顺序输出这组整数

  44. #include <stdio.h> #define MAX 100 intmain() { inta[MAX], i, j, n, t; scanf("%d", &n); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } for (i = 0, j = n-1; i < j; i++, j--) { t = a[i]; a[i] = a[j]; a[j] = t; } for (i = 0; i < n; i++) { printf("%d\n", a[i]); } return 0; }

  45. #include <stdio.h> #define MAX 100 intmain() { inta[MAX], i, j, n, t; scanf("%d", &n); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } for (i = 0, j = n-1; i < j; i++, j--) { t = a[i]; a[i] = a[j]; a[j] = t; } for (i = 0; i < n; i++) { printf("%d\n", a[i]); } return 0; }

  46. 练习7:循环右移数组中的元素 • 接收从控制台输出的一组整数(假设输入n个整数,n <= 100) • 将数组中后m个数移动到数组头部 • 要求不能使用辅助数组

  47. #include <stdio.h> #define MAX 100 intmain() { inta[MAX], i, j, m, n, t; scanf("%d%d", &n, &m); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } for (j = 0; j < m; j++) { t = a[n-1]; for (i = n-1; i > 0; i--) { a[i] = a[i-1]; } a[0] = t; } for (i = 0; i < n; i++) { printf("%d\n", a[i]); } return 0; }

  48. #include <stdio.h> #define MAX 100 intmain() { inta[MAX], i, j, m, n, t; scanf("%d%d", &n, &m); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } for (j = 0; j < m; j++) { t = a[n-1]; // 保存最后一个元素 for (i = n-1; i > 0; i--) { a[i] = a[i-1]; // 每个元素向右移动一步 } a[0] = t; // 将保存的最后一个元素移动到首位置 } for (i = 0; i < n; i++) { printf("%d\n", a[i]); } return 0; }

  49. …// 省略 inta[MAX], i, j, m, n, t, o, p, x; …// 省略 o = m; p = n; t = o % p; while (t != 0) { o = p; p = t; t = o % p; } // 求 p 为 n 和 m 的最大公约数 o = n / p; for (j = i = 0; j < p; j++) { t = a[i]; // t 为要右移的元素值 for (k = 1; k < o; k++) { i = (i + m) % n; // 计算移动的目标位置 x = t; // t 与 a[i] 交换 t = a[i]; a[i] = x; } a[j] = t; // 最后的 t 移到a[j]处 } …// 省略

  50. 课堂作业:选择性输出 • 问题描述 • 分别按顺序输出输入的自然数和负整数。 • 程序输入 • 第一个整数为输入整数数量n(n<100) • 紧跟着n个整数(可能是正整数,零或负整数) • 程序输出 • 先按输入顺序输出所有的自然数; • 再按输入顺序输出所有的负整数; • (注:每个整数占一行)。 课堂 作业 在纸上写出这段程序,标上姓名、学号; 写完后,交给我,即可离开。

More Related