1 / 75

Chap 7 数 组

Chap 7 数 组. 7.1 投票情况统计 7.2 找出矩阵中最大值所在的位置 7.3 判断回文. 本章要点. 什么是数组? 为什么要使用数组?如何定义数组? 如何引用数组元素? 二维数组的元素在内存中按什么方式存放? 什么是字符串? 字符串结束符的作用是什么? 如何实现字符串的存储和操作,包括字符串的输入和输出? 怎样理解 C 语言将字符串作为一个特殊的一维字符数组?. 7.1 投票情况统计. 输入一个正整数 n (1<n ≤ 10) , 再输入 n 个整数, 用选择法将它们从小到大排序后输出。 7.1.1 程序解析

feo
Download Presentation

Chap 7 数 组

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. Chap7 数 组 7.1 投票情况统计 7.2 找出矩阵中最大值所在的位置 7.3 判断回文

  2. 本章要点 • 什么是数组? 为什么要使用数组?如何定义数组? • 如何引用数组元素? • 二维数组的元素在内存中按什么方式存放? • 什么是字符串? 字符串结束符的作用是什么? • 如何实现字符串的存储和操作,包括字符串的输入和输出? • 怎样理解C语言将字符串作为一个特殊的一维字符数组?

  3. 7.1 投票情况统计 输入一个正整数n (1<n≤10),再输入n个整数, 用选择法将它们从小到大排序后输出。 7.1.1 程序解析 7.1.2 一维数组的定义和引用 7.1.3 一维数组的初始化 7.1.4 使用一维数组编程

  4. 7.1.1 程序解析 【例7-1】调查电视节目欢迎程度。某电视台要进行 一次对该台8个栏目(设相应栏目编号为1~8)的受欢 迎情况,共调查了1000位观众,现要求编写程序, 输入每一位观众的投票,每位观众只能选择一个最 喜欢的栏目投票,统计输出各栏目的得票情况。 分析: 本题涉及新问题 • 如何存储8个栏目计票数据

  5. 例7-1程序 # include<stdio.h> int main( void ) { int i,response,count[9]; /* 设立得票计数器*/ for(i = 1;i <= 8;i++) count[i] = 0; /*得票计数器清0 */ for( i = 1;i <= 1000;i++) { printf("input your response: "); /* 输入提示 */ scanf("%d",&response); if(response < 1 || response > 8) /* 检查是否有效票*/ printf("this is a bad response: %d\n",response); else count[response]++; /* 对应栏目得票加1 */ } printf("result:\n"); /* 输出得票情况 */ for(i = 1;i <= 8;i++) printf("%4d%4d\n",i,count[i]); return 0; }

  6. 7.1.2 一维数组的定义和引用 1. 数组的一般概念 • 数组是按序排列的同类型变量的集合,是一组具有相 同名字, 不同下标的下标变量。 • 下标变量又称数组元素,形式为:数组名[下标] 如:a[0]、a[1]、a[2]、a[3]、…、a[9] • 数组名表示整个数组,如:a • 下标指出该数组元素在数组中的位置。 • 有1个下标的下标变量所组成的数组称为一维数组; 有2个下标的下标变量所组成的数组称为二维数组。 如:x[1]、y[5] 数组x和y都是一维数组 a[1][2]、b[2][3] 数组a和b都是二维数组

  7. 7.1.2 一维数组的定义和引用 2. 一维数组的定义 • 定义的一般形式 类型名数组名[数组长度]; • 类型名:数组元素的数据类型 • 数组名:数组的名称,标识符 • 数组长度:常量表达式,指定数组元素的个数 例如: int a[10]; 定义一个含有10个整型元素的数组a char c[81]; 定义一个含有81个字符元素的数组c float f[5]; 定义一个含有5个实型元素的数组 f

  8. a[0] a[1] a[9] … … 7.1.2 一维数组的定义和引用 • 数组中元素的下标从0开始依次编号。 • 经定义的数组,编译后,会分配到一段 连续的内存单元。如有定义int a[10]; , 情况如图所示,a[0],a[1],…, a[9]依 次连续存储。 • 数组名(如a )是一个地址常量,存放 数组内存空间的首地址。也就是第1 个元素的存储地址,即a和&a[0]同值。 • 各个元素的存储地址用数组的首地址以及每个元 素所需的字节数,均可计算得到。

  9. 7.1.2 一维数组的定义和引用 • 数组定义中的数组长度只能是常量表达式,不能 含变量。如以下定义是非法的: int n, m=10; double a[n], b[m]; • 同类型数组、变量可一起定义: int i, a[10], b[20];

  10. 7.1.2 一维数组的定义和引用 3. 一维数组的引用 只能引用单个数组元素,不能一次引用整个数组。 数组元素的引用方法有两种:下标法和指针法。 • 下标法引用一维数组元素的形式为: 数组名[下标] 其中下标为整型表达式,取值范围是:[0, 数组长 度-1],它表示了元素在数组中的顺序位置。 • 数组元素又称下标变量,使用方法与同类型变量 完全相同。 • 编译时,不检查数组元素的下标是否越界。

  11. 7.1.3一维数组的初始化 数组初始化就是在定义数组时,对数组元素赋值。 其一般形式为: 类型名 数组名[数组长度] = {初值表}; • 初值表中用逗号分隔的各值为将依次赋予各对应 元素的初值,必须是常量表达式,且类型应与数 组的类型相一致。例如, int a[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; • 字符数组初始化有两种形式 • char b[6]={'C','h','i','n','a','\0'}; • char s[6]={"China"}; 或 char s[6]="China";

  12. 7.1.3一维数组的初始化 • 允许只给部分元素赋初值(其余元素初始化为0 )。 如:int a[10]={1, 2, 3}, b[10]={ 0 }; • 如对全部元素都赋初值,可缺省数组长度,数组 长度为初值表中初值的个数。例如, int a[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; char s[]="China"; • 对数组未指定初始化 • 自动类型数组,各元素的值是随机的未知值。 • 全局数组和静态数组,各元素值则会自动初始 化为0。

  13. 7.1.3一维数组的初始化 • 一维数组的输入和输出 • 对数组元素赋初值,更多的是通过键盘输入的 方法。如输入长度为n的整型数组a的各元: for( i=0; i<n; i++ ) scanf("%d", &a[i]); • 输出长度为n的整型数组a的各元: for( i=0; i<n; i++ ) printf("%d ", a[i]);

  14. 7.1.4 使用一维数组编程 【例7-2】利用数组计算 fibonacci 数列的前 10 个 数,即 1, 1, 2, 3, 5, …, 35,并按每行打印5个数的 格式输出。 分析: 本题与【例4-11】的差别仅是先将算出的各项值 存入数组,最后再输出。 定义数组并初始化:int i, fib[10] = {1, 1}; 初始条件: fib[0]=1, fib[1]=1 ( i = 0, 1 ) 递推公式:fib[i]= fib[i-1]+ fib[i-2] ( i > 1 )

  15. 例7-2程序 #include <stdio.h> int main(void) { int i, fib[10] = {1, 1}; for(i = 2; i < 10; i++) fib[i] = fib[i - 1] + fib[i - 2]; for(i = 0; i < 10; i++) { printf("%6d", fib[i]); if((i + 1)%5==0) printf("\n"); } return 0; } 运行结果: 1 1 2 3 5 8 13 21 34 55

  16. 7.1.4 使用一维数组编程 【例7-3】输入5个整数,将它们存入数组 a 中,再 输入一个数x,然后在数组中查找x,如果找到,输 出相应的最小下标,否则,输出“Not Found”。 分析: 这是个查找问题中的顺序查找问题。 • 通过遍历(扫描)数组a,对数组各元逐个比较是否 等于x即可。 • 最后判断是否未找到,可用标志法或break法。

  17. i == 5 例7-3程序 #include <stdio.h> int main(void) { int i, flag, x,a[5]; printf("Enter 5 integers: "); for(i = 0; i < 5; i++) scanf("%d", &a[i]); printf("Enter x: "); scanf("%d", &x); for(flag = i = 0; i < 5; i++) if(a[i] == x) {printf("Index is %d\n", i); flag = 1; break; } if(flag == 0)printf("Not Found\n"); return 0; } 运行结果1: Enter 5 integers: 2 9 8 1 6 Enter x: 9 Index is 1 运行结果2: Enter 5 integers: 2 9 8 1 6 Enter x: 7 Not Found

  18. 7.1.4 使用一维数组编程 【例7-4】输入一个正整数n(1< n <11), 再输入n个 整数,将它们存入数组 a 中。 ① 输出最小值和它所对应的下标。 ② 将最小值与第一个数交换,输出交换后的n个数。 分析: ① 这是个求最值问题。可先假定a[0]最小,即最小 元素的下标index=0,然后遍历数组a,各元素逐个 与a[index]比较,若小于,则其下标存入index,这 样就是使 index 中始终是到当前为止的最小元素的 下标 。

  19. 7.1.4 使用一维数组编程 实现语句: for(index = i = 0; i<n; i++) if(a[i] < a[index]) index = i; ② 交换两个变量的值有多种方法: • 借助第三者 t = a; a = b; b = t; • 不借助第三者 a =a+b; b= a-b; a =a-b; a ^= b; b ^=a; a ^= b; 或写成 a ^= b ^= a ^= b;

  20. 例7-4程序 #include <stdio.h> int main(void) { int i, index, n, a[10], t; printf("Enter n: "); scanf("%d", &n); printf("Enter %d integers: ", n); for(i = 0; i < n; i++) scanf("%d", &a[i]); for(index = 0, i = 1; i < n; i++) if(a[i] < a[index]) index = i; printf("min is %d\tsub is %d\n",a[index],index);

  21. 例7-4程序 t = a[index]; a[index] = a[0]; a[0]=t; for(i = 0; i < n; i++) printf("%d ", a[i]); return 0; } 运行结果: Enter n: 6 Enter 6 integers: 2 9 -1 8 1 6 min is -1 sub is 2 -1 9 2 8 1 6

  22. 7.1.4 使用一维数组编程 【例7-5】选择排序法。输入一个正整数n(1< n ≤ 10),再输入n个整数,用选择法将它们从小到大排 序后输出。

  23. 例7-5程序 #include <stdio.h> int main(void) { int i, j, k, n, t, a[10]; printf("Enter n: "); scanf("%d", &n); printf("Enter %d integers: ", n); for(i = 0; i < n; i++) scanf("%d", &a[i]); for(i = 0; i < n-1; i++) { for(k = i, j = i+1; i < n; i++) if(a[j] < a[k]) k = j; t = a[i]; a[i]=a[k]; a[k]=t; }

  24. 例7-5程序 printf("After sorted: "); for(i = 0; i < n; i++) printf("%d ", a[i]); return 0; } 运行结果: Enter n: 10 Enter 10 integers: 3 5 2 8 1 22 89 0 -1 7 After sorted: -1 0 1 2 3 5 7 8 22 89

  25. 选择法排序 选择法排序的基本思想是: 通过比较找到最小数,如不是第1个数,则与第1 个数交换,再在余下的数(即第2个开始)中找到最 小数,如不是第 2 个数,则与第 2 个数交换,再在 余下的数(即第3个开始)中找到最小数,如不是第 3 个数,则与第 3 个数交换,依此类推,n 个数经过 n-1 轮比较即可完成排序。

  26. 选择法排序 选择法排序的实现1: int n=5, i, j, t; int a[5] = {3, 5, 2, 8, 1}; for(i = 0; i < n-1; i++) for( j = i+1; j < n; j++) if(a[i]>a[j]) { t = a[i]; a[i] = a[j]; a[j] = t; }

  27. i = 0 F i < n-1 end i ++ T j = i+1 F j < n T a[i]>a[j] F j ++ T 交换a[i],a[j] 选择法排序的实现1流程:

  28. 选择法排序 选择法排序的实现2: int n=5, i, j, k, t; int a[5] = {3, 5, 2, 8, 1}; for(i = 0; i < n-1; i++) { for(k=i, j=i+1; j<n; j++) if(a[k]>a[j]) k = j; if(k != i) { t=a[i]; a[i]=a[j]; a[j]=t; } }

  29. i = 0 i < n-1 F end T k=i, j=i+1 j < n F T a[k]>a[j] F F k != i T T 交换a[i],a[k] k = j i ++ j ++ 选择法排序的实现2流程:

  30. 冒泡法排序 冒泡法排序1的基本思想是: 从第n个数开始,依次比较相邻两个数,即第n个 与第n-1个、第n-1个与第n-2个、… ,每次比较, 若不满足由小到大的顺序,则两者对调位置,通过 一轮比较,参加比较的数中的最小数就“上升”到它 们中最前面的位置,下一轮再从第n个数开始,把 余下的数依次比较,这样,通过n-1轮比较,就完 成了全部n个数的升序排列。在第i轮比较时,从第 1个位置开始已排序定位了i-1个数,余下n-i+1个 数,需两两比较 n-i次。

  31. 冒泡法排序 冒泡法排序1的实现: int n=5, i, j, t; int a[5] = {3, 5, 2, 8, 1}; for(i = 0; i < n-1; i++) for( j = n-1; j > i; j--) if(a[j] < a[j-1]) { t = a[j]; a[j] = a[j-1]; a[j-1] = t; }

  32. 冒泡法排序 冒泡法排序2的基本思想是: 从第1个数开始,依次比较相邻两个数,即第1个 与第2个、第2个与第3个、… ,每次比较,若不满 足由小到大的顺序, 则两者对调位置, 通过一轮 比较,参加比较的数中的最大数就 “ 下沉 ” 到它们 中最后面的位置,下一轮再从第1个数开始,把余 下的数依次比较,这样,通过n-1轮比较,就完成 了全部n个数的升序排列。在第i轮比较时,从第 n 个位置开始向前已排序定位了i-1个数,余下 n-i+1 个数,需两两比较n-i次

  33. 冒泡法排序 冒泡法排序2的实现: int n=5, i, j, t; int a[5] = {3, 5, 2, 8, 1}; for(i = 0; i < n-1; i++) for( j = 0; j < n-1-i ; j--) if(a[j] > a[j+1]) { t = a[j]; a[j] = a[j+1]; a[j+1] = t; }

  34. 7.1.4 使用一维数组编程 【例7-6】二分查找法。设已有一个10个元素的整 形数组a,且按值从小到大有序。输入一个整数 x, 然后在数组中查找x,如果找到,输出相应的下标, 否则,输出“Not Found”。 设:待查数在变量x中; 变量low用于存放查找范围的顶部位置; 变量mid用于存放查找范围的中间位置; 变量high用于存放查找范围的底部位置;

  35. 输入x low=0;hghi=n-1; F low<=hghi T mid=(low+high)/2 F x!=a[mid] T T F x<a[mid] hghi=mid-1 low=mid+1 T F low<=hghi 输出mid Not found 二分法查找流程图

  36. 例7-6程序 #include <stdio.h> int main(void) { int low, high, mid, n=10, x, a[10]={1,2,3,4,5,6,7,8,9,10}; printf("Enter x: "); scanf("%d",&x); low = 0; high = n - 1; while (low <= high) { mid = (low + high) / 2; /* 中间位置 */ if (x == a[mid]) break; /* 找到,中止循环 */ else if (x < a[mid]) high = mid - 1; /* 前半段, high前移 */ else low = mid + 1; /* 后半段, low后移 */ } if(low <= high) printf("Index is %d \n",mid); else printf( "Not Found\n"); return 0; } 运行结果1: Enter x: 8 Index is 7 运行结果2: Enter x: 71 Not Found

  37. 7.2 找出矩阵中最大值所在的位置 将1个3*2的矩阵存入1个3*2的二维数组中,找出 最大值以及它的行下标和列下标,并输出该矩阵。 7.2.1 程序解析 7.2.2 二维数组的定义和引用 7.2.3 二维数组的初始化 7.2.4 使用二维数组编程

  38. 7.2.1 程序解析 【例7-7】将1个 3*2的矩阵存入1个 3*2 的二维数组 中,找出最大值以及它的行下标和列下标,并输出 该矩阵。 分析: • 涉及新问题:二维数组 • 求最值方法与【例7-4】①的一维数组中求最值方 法类似。 • row记录最大值的行下标 col 最大值的列下标 a[row][col] 就是最大值

  39. 例7-7程序 #include <stdio.h> int main(void) { int i, j, col, row,a[3][2]; printf("Enter 6 integers:\n") ; for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) scanf("%d", &a[i][j]); for(i = 0; i < 3; i++) { for(j = 0; j < 2; j++) printf("%4d", a[i][j]); printf("\n"); }

  40. 例7-7程序 运行结果: Enter 6 integers: 3 2 10 -9 6 -1 3 2 10 -9 6 -1 max = a[1][0] = 10 row = col = 0; for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) if(a[i][j] > a[row][col]) { row = i; col = j; } printf("max = a[%d][%d] = %d\n", row, col, a[row][col]); return 0; }

  41. a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] 7.2.2 二维数组的定义和引用 1. 二维数组的定义 • 定义的一般形式 类型名数组名[行长度][列长度] 其中行长度和列长度只能是常量表达式。 如: int a[3][2]; 定义3行2列的二维数组a, 各元素为: a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] 如图所示,按行存放在一段连续的内存中。

  42. 7.2.2 二维数组的定义和引用 • 二维数组是一维数组的数组 可以把a看作含有a[0]、a[1]和a[2]共3个元素的一 维数组,而a[0]、a[1]和a[2]又都是含有2个元素 的一维数组,a[0]、a[1]和a[2]就是这3个一维数 组的名字,即: a:a[0]: a[0][0] a[0][1] a[1]: a[1][0] a[1][1] a[2]: a[2][0] a[2][1]

  43. 7.2.2 二维数组的定义和引用 2. 二维数组的引用 数组元素的引用方法有两种:下标法和指针法。 下标法引用二维数组元素的形式为: 数组名[行下标] [列下标] 其中: 行、列下标 可以是整型表达式; 行下标 取值范围: [0, 行长度-1]; 列下标 取值范围:[0, 列长度-1]。

  44. 7.2.3 二维数组的初始化 1. 分行赋初值的一般形式 类型名数组名[行长度][列长度] = { {初值表0}, … … , {初值表k},…}; 其中初值表k中的数据依次赋给k行的元素。 例如:int a[3][2]={{1,2},{3,4},{5,6}}; 2. 顺序赋初值的一般形式 类型名数组名[行长度][列长度] = {初值表}; 按数组元素在内存中的存放顺序,把初值表中的数 据依次赋给元素。 例如:int a[3][2]={1,2,3,4,5,6};

  45. 7.2.3 二维数组的初始化 3. 初始化说明 • 允许只给部分元素赋初值(其余元素初始化为0) int a[3][4]={{8,4}, {5}, {4}}; int a[3][4]={8,4,2,1,5}; • 当用分行赋值给出了所有行,或者当用顺序赋值给出全部数组元素初始化值时,可以缺省行长度 int a[ ][4]={{8,4}, {5},{4}}; int a[ ][4]= {8,4,2,1, 5,7,0,3, 4,0,9,6}; • 对数组未指定初始化 • 自动类型数组,各元素值是随机的未知值。 • 全局数组和静态数组,各元素值自动赋初值0。

  46. 7.2.3 二维数组的初始化 • 二维数组的输入和输出 • 对数组元素赋初值,更多的是通过键盘输入的方法。 如输入n行m列的整型数组a的各元: for( i=0; i<n; i++ ) for( j=0; j<m; j++ ) scanf("%d", &a[i]); • 输出n行m列的整型数组a的各元: for( i=0; i<n; i++ ) { for( j=0; j<m; j++ ) printf("%d ", a[i]); printf("\n"); }

  47. 7.2.4 使用二维数组编程 【例7-8】定义1个 3*2的二维数组a,数组元素的值 由下式给出,按矩阵的形式输出a。 a[i][j] = i + j(0≤i≤2,0≤j≤1)

  48. 例7-8程序 运行结果: 0 1 1 2 2 3 #include <stdio.h> int main(void) { int i, j, a[3][2]; for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) a[i][j] = i + j; for(i = 0; i < 3; i++) { for(j = 0; j < 2; j++) printf("%4d", a[i][j]); printf("\n"); } return 0; }

  49. 7.2.4 使用二维数组编程 【例7-9】输入一个正整数n(1<n≤6),根据下式 生成1个n*n的方阵,然后将该方阵转置(行列互换) 后输出。 a[i][j] = i * n + j + 1(0≤i≤n-1,0≤j≤n-1) 例如,当n=3时,有: 转置前 转置后 1 2 3 1 4 7 4 5 6 2 5 8 7 8 9 3 6 9

  50. 副对角线i+j==N-1 上三角i<=j 下三角i>=j 主对角线i==j 7.2.4 使用二维数组编程 矩阵术语与二维数组下标的对应关系: int a[N][N]; N是正整数 a[i][j]:i、j的取值范围[0,N-1] 设N为3,用二维数组a表示N*N方阵时: a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] a[2][0] a[2][1] a[2][2]

More Related