数组:
1 数组的引入和基本语法

1)有些问题的解决需要我们保留大量的数据。
案例:班上有10个同学,根据班上同学的平均分调节同学的成绩,如果平均分小于55分,则每个同学都提高10分。
#include <stdio.h> int main() { int score[10] = {60,70,30,50,56,56,60,70,30,50}
; // 求出同学们成绩的平均分 int i; int sum = 0; for(i=0; i<10; ++i) { sum += score[i]; }
// 求平均分 int m = sum/10; printf("%d\n", m); if(m<55) { // 每个同学的成绩提高10分 for(i=0; i
<10; ++i) { score[i] += 10; } } // 输出数组中的每个元素 for(i=0; i<10; ++i){ printf("%3d",
score[i]); } return 0; }
如果要求从键盘上录入同学的成绩
for(i=0; i<10; ++i) {   scanf("%d", &score[i]); }
2)数组定义语法
数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
数组元素在内存中的存放位置是连续的。

3)数组元素的初始化
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0}; double balance[] = {1000.0,
2.0, 3.4, 7.0, 50.0};
4)数组元素的使用

访问和修改
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。
可以读取数组中的元素也可以修改数组中元素的值。
位置下标是从0开始的。 最后一个元素的下标是N-1(假设数组容量是N个元素)

注意访问元素的时候下标不要越界。
int score[10] = {60,70,30,50,56,56,60,70,30,50}; score[0];
5)获得数组的大小(字节数),获得数组中的元素数量

2 使用数组的典型案例

1)存储大量数据并完成针对大量数据的算法,最基础的问题,算法简单(不用数组也可以完成,但是不能保留所有的数据)
找到这些数据中的最大值或者最小值。
#include <stdio.h> int main() { int a[5] = {2,3,7,5,1}; int m = a[0]; for(int i
=1; i<5; i++){ if(a[i]>m){ m = a[i]; } } printf("max is %d\n", m); return 0; }
扩展:在找最大值的同时,要给出最大值所在的位置编号。
#include <stdio.h> int main() { int a[5] = {2,3,7,5,1}; int m = a[0]; int pos =
0; for(int i=1; i<5; i++){ if(a[i]>m){ m = a[i]; pos = i; } } printf("max is %d
at %d\n", m, pos); return 0; }
在数据中查找是否存在某个数(或者符合某种条件的某个数),找到返回该数在序列中的位置,找不到返回-1.
#include <stdio.h> int main() { int a[5] = {2,3,7,5,1}; int n = 3; int pos = -1
; for(int i=0; i<5; i++){ if(a[i]==n){ pos = i; break; } } if(pos==-1) printf(
"not find"); else{ printf("find at %d", pos); } return 0; }
2)用数组保存统计结果。例题:输入一个整数(可能很长),统计整数中每个数字出现的次数。
如 输入1124511, 输出 0:0, 1:4,2:1,3:0,4:1,5:1,6:0,7:0,8:0,9:0
用一个数组来保存数字的数量,a[0]保存0的数量,a[9]保存9的数量,int a[10]
取得输入的整数中的每一位数字,让后对对应数组的统计元素进行加一操作。

怎样取到整数中的每一位?(整数分离,可以用循环)
怎么处理很长的整数?(所以不能使用整型变量)
#include <stdio.h> int main() { char c; int a[10] = {0}; c = getchar(); //
c='1' // 在输入的同时完成数字数量的统计 while(c!='\n'){ a[c-'0']++; // '1' - '0' c = getchar();
} // 按照题目要求打印输入统计结果(统计数组) for(int i=0; i<10; i++){ printf("%d:%d\n", i, a[i]); }
return 0; }
扩展1,输入字母组成的字符串,统计每个字母出现的次数。(有26个元素的数组来存储字母出现的数量,可能还有考虑大小写字母,字母对应下标 c-‘a’)

扩展2,输入字母和数字组成的字符串,统计每个数字和字母出现的次数。(多个数组,有些存储数组数量,有些存储字母数量)

扩展3,输入字母、数字、空格和其他字符组成的字符串,统计字母(字母的总数)、数字(数字总数)、空格和其他字符的个数。(可以不用数组)

3)存储一系列的数,辅助完成迭代算法。斐波拉契数列之数组版。
#include <stdio.h> int main() { int a[10] = {0}; a[0] = 1; a[1] = 1; for(int i=
2; i<10; i++){ a[i] = a[i-1] + a[i-2]; printf("%d ", a[i]); } return 0; }
4)存储大量数据,完成针对大量数据的算法,进阶问题及算法。
选择排序
#include <stdio.h> int main() { const int n = 5; int a[5] = {3, 2, 4, 5, 1};
for(int i=0; i<n-1; i++){ // 在a[i]到a[n-1]范围中找到最小并且记录最小值的位置,并放置在i位置处(和a[i]交换) int
m= a[i], k; int j; for(j=i+1, k=i; j<n; j++){ if(a[j]<m){ m = a[j]; k = j; } }
// 交换 a[k] 和 a[i] int t = a[i]; a[i] = a[k]; a[k] = t; } // 输出数组 for(int i=0; i<
n; i++){ printf("%4d", a[i]); } return 0; }
扩展,1)从大到小。 2)学号数组和成绩数组,一一对应关系。按照成绩的升序输出学号(姓名)。(按照成绩数组排序,同时交换对应的学号)
冒泡排序
#include <stdio.h> int main() { const int n = 5; int a[5] = {3, 2, 4, 5, 1};
for(int i=0; i<n-1; i++){ for(int j=0; j<n-1-i ;j++){ // 两两比较,大于则交换 if(a[j]>a[j+
1]){ int t = a[j]; a[j] = a[j+1]; a[j+1] = t; } } } // 输出数组 for(int i=0; i<n; i
++){ printf("%4d", a[i]); } return 0; }
插入排序
归并排序


查找
暴力查找
二分查找(效率更高,但是要求数组中的元素是有序的)
#include <stdio.h> int main() { const int n = 5; int a[5] = {1, 2, 3, 4, 5};
int s=0, e=n-1; int x = 8; int pos = -1; while(s<=e){ int mid = (s+e)/2; if(a[
mid]==x){ pos = mid; break; }else if(x>a[mid]){ s = mid+1; }else if(x<a[mid]){ e
= mid-1; } } if(pos==-1){ printf("not find\n"); }else{ printf("found %d at %d\n"
, x, pos); } return 0; }
5) 用数组存储好固定的数据,代码中直接提取使用,避免繁琐和反复的计算。

计算某年的某个月有多少天?
可以将每个月的天数提前存入一个表示天数的数组中,然后将月份作为数组的下标进行对应,直接从数组中取出,让代码的逻辑和实现都变得很简单了。
举例,计算日期是该年的第几天?
#include <stdio.h> int is_leap(int y) { return ((y%4==0&&y%100!=0) || y%400==0)
; } int main() { int a[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273,
304, 334}; // 每个月之前当年有多少天 int y = 2000; int m = 3; int res = a[m]; if (m>=3 &&
is_leap(y)) res += 1; printf("%d\n", res); return 0; }
6)必须先把大量的数据保存下来,才能进行后续的处理。
入门案例(见上面的例题)
整数分解,正序输出每个数字。详细讲解参考MOOC B。
还有其他更好的解决方案吗?(使用数组)
反序取到每个数字,将他们存入数组中,反序输出数组。
#include <stdio.h> #include <math.h> int main() { int a=187; int num[100]; int
i=0; int d; do{ d = a%10; num[i] = d; i++; a /= 10; }while(a>0); for(int j=i-1;
j>=0; j--){ printf("%4d", num[j]); } return 0; }
例题:本题要求计算 /,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。
输入格式:
输入在一行中依次给出 A 和 B,中间以 1 空格分隔。
输出格式:
在一行中依次输出 Q 和 R,中间以 1 空格分隔。
输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3
#include <stdio.h> int main() { int a[1001] = {0}; char c; int i = 0; while((c=
getchar())!=' ') { a[i++] = c-'0'; } int b; scanf("%d", &b); int yu = 0; for(int
j=0; j<i; j++) { int tem = yu*10+a[j]; a[j] = tem/b; yu = tem%b; } int b_first
= 1; for(int j=0; j<i; j++) { if(b_first){ if(a[j]!=0){ printf("%d", a[j]);
b_first= 0; } } else printf("%d", a[j]); } if(b_first) printf("0"); printf(" %d"
, yu); return 0; }
二维数组
1 二维数组的意义及基本语法
1)意义
有两个维度,可以被认为是行列结构。想象一下二维结构的图像。
2)定义及初始化
int x[3][4]; int a[3][4] = { {0, 1, 2, 3} , /* 初始化索引号为 0 的行 */ {4, 5, 6, 7} ,
/* 初始化索引号为 1 的行 */ {8, 9, 10, 11} /* 初始化索引号为 2 的行 */ }; int a[3][4] = {0,1,2,3,4
,5,6,7,8,9,10,11};
二维数组的元素在内存空间中是连续存放的,以行的顺序进行展开成一个一维结构。

3)引用及访问修改
a[1][2]
通常会结合二重循环来访问每个元素。

2 二维数组的典型应用

1)存储二维结构数据,对二维数据进行统计
做成绩表,很多个同学,学了多个科目。
二维表格,成绩表,一行代表一个同学,一列代表一门科目。
所有成绩的总分及平均分。 每个科目的平均分。 每个同学的平均分。

2)模拟针对矩阵的操作
矩阵转置
题目内容:
用二维数组作为函数参数,编程计算并输出n×n阶矩阵的转置矩阵。其中,n的值不超过10,n的值由用户从键盘输入。
程序运行结果示例1:
Input n:3↙
Input 33 matrix:
1 2 3↙
4 5 6↙
7 8 9↙
The transposed matrix is:
1 4 7
2 5 8
3 6 9
程序运行结果示例2:
Input n:2↙
Input 22 matrix:
1 2↙
4 5↙
The transposed matrix is:
1 4
2 5
#include <stdio.h> int main() { int a[10][10]; printf("Input n:"); int n; scanf
("%d", &n); printf("Input %d*%d matrix:\n", n, n); for(int i=0; i<n; i++){ for(
int j=0; j<n; j++){ scanf("%d", &a[i][j]); } } for(int i=0; i<n; i++){ for(int j
=0; j<i; j++){ int t = a[i][j]; a[i][j] = a[j][i]; a[j][i] = t; } } printf("The
transposed matrix is:\n"); for(int i=0; i<n; i++){ for(int j=0; j<n; j++){
printf("%4d", a[i][j]); } printf("\n"); } return 0; }
检验并打印幻方矩阵
题目内容:

幻方矩阵是指该矩阵中每一行、每一列、每一对角线上的元素之和都是相等的。从键盘输入一个5×5的矩阵并将其存入一个二维整型数组中,检验其是否为幻方矩阵,并将其按指定格式显示到屏幕上。
输入格式: “%d”
输出格式:
如果是幻方矩阵,输出提示信息: “It is a magic square!\n”
矩阵元素的输出: “%4d”(换行使用"\n")
如果不是幻方矩阵,输出提示信息: “It is not a magic square!\n”
输入样例1:
17_24_1_8_15
23_5_7_14_16
4_6_13_20_22
10_12_19_21_3
11_18_25_2_9
(输人样例中“”代表空格)
输出样例1:
It is a magic square!
17241815
23571416
46132022
10121921*3
111825***2**9
(输出样例中“”代表空格)
输入样例2:
1_0_1_6_1
3_1_1_1_1
1_1_1_1_2
1_1_1_1_1
9_1_7_1_1
(输人样例中“”代表空格)
输出样例2:
It is not a magic square!
先求出矩阵第一行所有元素的和,放入sum中,再求其他行或者列或者对角线的和,其他的和都等于sum,说明是,否则不是。
#include <stdio.h> #include <math.h> int main() { int a[5][5]; int n = 5; int i
, j; for(i=0; i<5; i++){ for(j=0; j<5; j++){ scanf("%d", &a[i][j]); } } int flag
= 1; int s = 0; for(i=0; i<n; i++){ s += a[i][0]; } int s1 = 0; for(i=0; i<n; i
++){ s1 += a[i][n-1]; } if(s1!=s) flag = 0; s1 = 0; for(j=0; j<n; j++) s1 += a[0
][j]; if(s1!=s) flag = 0; s1 = 0; for(j=0; j<n; j++) s1 += a[n-1][j]; if(s1!=s)
flag= 0; s1 = 0; for(i=0; i<5; i++){ s1 += a[i][i]; // 对角线上的元素 } if(s1!=s) flag
= 0; s1 = 0; for(i=0; i<5; i++){ s1 += a[i][n-1-i]; // 反对角线上的元素 } if(s1!=s) flag
= 0; if(flag==1){ printf("It is a magic square!\n"); for(i=0; i<5; i++){ for(j=0
; j<5; j++){ printf("%4d", a[i][j]); } printf("\n"); } } else{ printf("It is
not a magic square!\n"); } return 0; }
找鞍点
#include<stdio.h> int main(void) { int a[10][10]; int m, n; scanf("%d%d", &m, &
n); for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ scanf("%d", &a[i][j]); } }
// 提前储出每一行的最大值和每一列的最小值 int maxs[10] = {0}; for(int i=0; i<m; i++){ maxs[i] = a[i
][0]; for(int j=1; j<n; j++){ if(a[i][j]>maxs[i]){ maxs[i] = a[i][j]; } } } int
mins[10] = {0}; for(int j=0; j<n; j++){ mins[j] = a[0][j]; for(int i=1; i<m; i++
){ if(a[i][j]<mins[j]){ mins[j] = a[i][j]; } } } int flag = 0; for(int i=0; i<m;
i++){ for(int j=0; j<n; j++){ if(a[i][j]==maxs[i] && a[i][j]==mins[j]){ printf(
"Array[%d][%d]=%d\n", i, j, a[i][j]); flag = 1; } } } if(!flag){ printf("None\n"
); } return 0; }
蛇形矩阵填充
#include <stdio.h> int a[101][101]; void print(int a[][101], int n) { for(int i
=0; i<n; i++){ for(int j=0; j<n; j++){ printf("%4d", a[i][j]); } printf("\n"); }
} /* 按照对角线的顺序填充,利用对角线的序号奇偶性控制填充的方向,提前规划好每个对角线应该 填充的数量,在边界处进行处理 */ int main() {
int n; printf("Input n:\n"); int n_in = scanf("%d", &n); if(n_in!=1 || n>100 ||
n<=0){ printf("Input error!\n"); return 0; } int N = n*n; int line_no = 1,
num_in_line= 1; int m = 1; int i=0, j=0; while(m<=N){ // fill a line for(int k=0
; k<num_in_line; k++){ a[i][j] = m++; if(line_no%2==1){ if(i-1>=0 && j+1<=n-1) i
--, j++; } else{ if(i+1<=n-1 && j-1>=0) i++, j--; } } // end of line // locate
i, j for next line if(line_no<n){ if(line_no%2==1 && j<n-1) j+=1; if(line_no%2==
0 && i<n-1) i+=1; num_in_line++; } else{ if(line_no%2==1 && j==n-1) i+=1; if(
line_no%2==0 && i==n-1) j+=1; num_in_line--; } line_no++; } print(a, n); return
0; } #include <stdio.h> int a[101][101]; void print(int a[][101], int n){ for(
int i=0; i<n; i++){ for(int j=0; j<n; j++){ printf("%4d", a[i][j]); } printf(
"\n"); } } /* 从1开始填充 i_sign = -1, j_sign = +1; 边界及边界变化 j==n-1 --> i+=1; i==n-1
--> j+=1; i==0--> j+=1; j==0 --> i+=1; 边界处同时改变方向 i_sign *= -1; j_sign *= -1;
边界处同时填充下一个位置(新斜线的起点) a[i][j]=m++; 所有情况都移动位置 i += i_sign; j += j_sign;
注意在边界处应该将下一个位置填充后跳过下一个位置,应为边界处的下一个位置不应该被作为边界了 */ int main() { int n; printf(
"Input n:\n"); int n_in = scanf("%d", &n); if(n_in!=1 || n>100 || n<=0){ printf(
"Input error!\n"); return 0; } int N = n*n; //int line_no = 1, num_in_line = 1;
int m = 1; //a[0][0] = m++; int i=0, j=0, i_sign=-1, j_sign=1; while(m<=N){ a[i]
[j] = m++; if(j==n-1){ i+=1; a[i][j]=m++; i_sign *= -1; j_sign *= -1; }else if(i
==n-1){ j+=1; a[i][j]=m++; i_sign *= -1; j_sign *= -1; }else if(i==0){ j+=1; a[i
][j]=m++; i_sign *= -1; j_sign *= -1; }else if(j==0){ i+=1; a[i][j]=m++; i_sign
*= -1; j_sign *= -1; } i += i_sign; j += j_sign; } print(a, n); return 0; } #
include <stdio.h> int a[101][101]; void print(int a[][101], int n){ for(int i=0;
i<n; i++){ for(int j=0; j<n; j++){ printf("%4d", a[i][j]); } printf("\n"); } }
/* 从1开始填充 i_sign = -1, j_sign = +1; 边界及边界变化 j==n-1 --> i+=1; i==n-1 --> j+=1;
i==0--> j+=1; j==0 --> i+=1; 边界处同时改变方向 边界处同时填充下一个位置(新斜线的起点) a[i][j]=m++;
所有情况都移动位置 i += i_sign; j += j_sign;
注意在边界处应该将下一个位置填充后跳过下一个位置,应为边界处的下一个位置不应该被作为边界了 */ int can_step(int i, int j, int
i_sign, int j_sign, int n){ i+=i_sign; j+=j_sign; if(i<0||i>n-1||j<0||j>n-1)
return 0; else return 1; } int main() { int n; printf("Input n:\n"); int n_in =
scanf("%d", &n); if(n_in!=1 || n>100 || n<=0){ printf("Input error!\n"); return
0; } int N = n*n; int m = 1; int i=0, j=0, i_sign=-1, j_sign=1; while(m<=N){ a[i
][j] = m++; if(!can_step(i,j,i_sign,j_sign,n)){ if(j==n-1){ i+=1; }else if(i==n-
1){ j+=1; }else if(i==0){ j+=1; }else if(j==0){ i+=1; } i_sign *= -1; j_sign *=
-1; }else{ i += i_sign; j += j_sign; } } print(a, n); return 0; }
杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
#include<stdio.h> int main(void) { int a[10][10]; for(int i=0; i<10; i++){ a[i]
[0] = 1; a[i][i] = 1; } for(int i=2; i<10; i++){ for(int j=1; j<i; j++){ a[i][j]
= a[i-1][j] + a[i-1][j-1]; } } for(int i=0; i<10; i++){ for(int j=0; j<=i; j++){
if(j==0) printf("%d", a[i][j]); else printf(" %d", a[i][j]); } printf("\n"); }
return 0; }

技术
©2019-2020 Toolsou All rights reserved,
份额已超宁德时代!LG化学确认将分拆电池业务部门Qt学习7——模态和非模态对话框数字滚动抽奖小程序vue 监听 Treeselect 选择项的改变 dedecms网站被黑 劫持到其他网站如何解决内存溢出和内存泄漏的区别、产生原因以及解决方案SQL Server 数据库词汇表1190 反转每对括号间的子串 leetcode蝗灾虫群上亿只很少发生碰撞 蝗虫要成自动驾驶功臣最优化方法总结:公式解、数值优化、求解思想