0、解释
保存一个学生 成绩
int score;
保存10个学生 成绩
int score[10];
保存10个学生 10门科成绩
int score1[10]; //第1门科
int score2[10]; //第2门科
...
int score10[10]; //第10门科
二维数组 本质上还是一维数组
1、二维数组定义语法:
类型说明符 数组名[整数1][整数2];
类型说明符:
不是值数组的类型,而是数组里面的元素(数据)的类型,而是数组里面的元素
任意合法的C语言数据类型都可以
数组名:
数组的名字,符合C语言标识符规定,别和关键字一样
[整数1][整数2]:
可以是常量;值为整数的表达式 ; 可以为变量
二维数组 可以看作数学中 矩阵
整数1:行大小
整数2:列大小
元素个数:行大小 * 列大小 当作二维数组看
元素个数:行大小当作一维数组看
代表是数组的元素个数,一旦我们把数组定义好之后,该数组中元素的个数就不能变
2、怎么引用二维数组中的元素
下标法:
数组名[行下标][列下标];
行下标范围:[0,行大小)
列下标范围:[0,列大小)
防止下标越界
3、二维数组在内存中存放的顺序存储
int a[2][3];
二维数组中的各个元素在内存是连续的存储(24字节),先存储 第 0 行(a[0][0]、a[0][1]、a[0][2]) , 再存储第 1 行。
sizeof(a) <---> 求数组a所占字节个数
练习:
定义一个二维数组,依次从键盘输入数据给该数组各个元素赋值,然后打印输出
int a[3][4];
int i,j;
//输入:
for(i = 0;i < 3;i++)
{
for(j = 0;j < 4;j++)
{
scanf("%d",&a[i][j]);// 依次输入 每一行元素
}
}
/*
for(i = 0;i < 12;i++)// i = 3 a[0][3]
{
scanf("%d",&a[i/4][i%4]);// 依次输入 行列对应元素
}
*/
//输出:
for(i = 0;i < 3;i++)
{
for(j = 0;j < 4;j++)
{
printf("%d ",a[i][j]);// 依次输出 每一行元素
}
printf("\n");// 每输出一行 加个换行
}
4、二维数组初始化
数组的初始化 用 { }
(1)按行初始化
int a[3] = {1,2,3};
a.全部元素初始化
int a[2][3] = {{1,2,3},{1,2,3}};//全部赋值
b.部分元素初始化
int a[2][3] = {{1,2},{1}};//部分元素赋值
<====> int a[2][3] = {{1,2,0},{1,0,0}};
c.部分元素初始化,省略了行大小
int a[][4] = {{1,2,3},{1,2},{1,2,3,4}};// 可以省略 ,但是只能省略行大小
(2)不按行初始化,不分行,将所有元素写在一个{}中,依次对各个元素初始化
a.全部元素
int a[2][3] = {1,2,3,1,2,3};
b.部分元素初始化,其余的为默认值
int a[2][3] = {1,2,3,4};//部分元素赋值
<====> int a[2][3] = {{1,2,3},{4,0,0}};
c.部分元素初始化,可以不指定 行大小
int a[][3] = {1,2,3,4};
int a[][3] = {1,2,3,4,5,6,7}; //a[2][2] = 0;
编译器会根据{}中数值的个数以及列大小推导出行大小
无论哪种情况 都不能省略 列大小
练习:
初始化一个二维数组,且初始化,求最大值、最小值,以及最大值的下标
初始化一个二维数组a[i][j],定义一个二维数组b[j][i],把a的行列互换存到b里面去
a[2][3] = {1,2,3,4,5,6};
1 2 3
4 5 6
b[3][2];
1 4
2 5
3 6
练习:
打印杨辉三角前10行
(a+b)^0 = 1
(a+b)^1 = a + b
(a+b)^2 = a^2 + 2ab + b^2
(a+b)^3 = .....
.....
(a + b)^ n = a^n + ?a^(n-1)b ... + ?ab^(n-1)+ b^n
1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0 0 0 0
1 3 3 1 0 0 0 0 0 0
1 4 6 4 1 0 0 0 0 0
....
1 . . . . .. . 1
每一行 最开始 和 最末尾 系数都是1
从第2行开始中间值是 上一行的 前一位置 + 上一行的位置
求一个二维数组的“山顶元素” 的 个数
“山顶元素” 比周围元素都大 比 上下左右 4 个数都大
1 2 3 4 4
2 2 3 2
3 4 2 14
4 2 1 14
三个
①:加一圈最小值-1//自行思考
找到最小值 min
for(i = 0;i < 6;i++)
{
for(j = 0;j < 6;j++)
{
b[i][j] = min-1;
}
}
②:做判断
遍历:
把集合(数组) 中所有元素都访问一遍
找到一维数组中是否有某个数,如果有就打印下标
int a[5] = {5,2,9,6,4},i;
输入要找的数
输入了一个 4
for(i = 0;i < 5;i++)
{
if(a[i] == 4)
{
printf("%d",i);
}
}
在一个已经排好序(升序)的一维数组中查找一个数是否存在,如果有就打印下标
用上面的方法一样没有问题,但是是不是比较次数有点多
二分查找/折半查找
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int data;
二分查找/折半查找条件:
有序集合
支持随机访问
比普通查找优点在于:提高效率,减少了比较次数
时间复杂度:
普通查找:O(n)
二分查找:O(log2(n))
作业:
求二维数组的“鞍点” 个数
是当前行最大并且是当前列最小
1 2 3 4 4
2 2 3 2
3 4 2 9
4 2 1 9