2018 年 11 月 26 日,“洞察”号火星探测器在火星上成功着陆,执行人类首次探究火星“内 心深处”的任务。火星上地形比较复杂,高低起伏,有山峰和低谷,稍有不慎,就会引起“翻 车”。因此我们必须要识别地形上的各个最高点(峰点)和最低点(谷点),以便为探测器 提供导航数据。
峰点就是一个其周围所有点的海拔都低于它的点
203 | 109 | 181 |
289 | 300 | 264 |
190 | 250 | 188 |
现在我们要做的就是分析来自地图上的海拔数据,以确定地形中峰点的数目和位置
数组,就是多个同类型的元素的有序“组合”。如下的一组女兵,注:同类型是指都是女兵,不能混入男兵 -:)
二维数组,就是指含有多个数组的数组!
如果把一维数组理解为一行数据,那么,二维数组可形象地表示为行列结构。
和数组一样,需要先定义,再使用。
int a[25] ; //一行女兵实例:
int a[5][25]; //五行女兵
//定义了一个二维数组,
//数组名是“a”,
//包含 5 行 25 列,共 125 元素,
//每个元素是 int 类型的变量
int a[3][4]; //二维数组元素的值可能是随机的(全局变量会初始化为 0,局部变量值随机)
方式一 初始化时指定每行的值
int a[3][4]={ //等效于 int a[][4]
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
注:最外围括号内部的每个括号相当于初始化一行,括号中可以省略某些元素的初始化
方式二初始化时从头开始,依次序进行
int a[3][4]={ 1,2,3,4,5,6,7,8,9,10,11,12};
int a[3][4]={ 0}; //所有元素都初始化为 0
注:后面的多个元素可以不指定,不指定全部初始化为 0
#include <stdlib.h> #include int main(void){ //int ages[5][25];//定义一个二维数组 int i=0, j=0; //初始化 //第一种方式 初始化时指定每行的值 int a[3][4]={ {1},//省略掉得列会默认置零 {5,6,7}, {9,10,11,12} }; //第二种方式 初始化时从头开始,依次序进行 int a1[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int a2[3][4]={1};//只初始化第一个,其他得默认置零 for(i=0; i<3; i++){ for(j=0; j<4; j++){ printf("%d ", a[i][j]); } printf("\n"); } system("pause"); return 0; } |
a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
a[0][0] 1 | a[0][1] 2 | a[0][2] 3 | a[0][3] 4 |
a[1][0] 5 | a[1][1] 6 | a[1][2] 7 | a[1][3] 8 |
a[2][0] 9 | a[2][1] 10 | a[2][2] 11 | a[2][3] 12 |
如下图表示,左侧表示的是一个大小为M+1的一维数组,右侧表示的是一个大小为(M+1)*(N+1)的二维数组。
int i=0, j=0; int a[3][4]; //给数组成员赋值 for(int i=0;i<12; i++){ a[i/4][i%4] = i+1; } //或 for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ a[i][j] = 4*i+j+1; } } |
//输出 for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]); } printf("\n"); } | 11 |
设置断点调试,可以看到二位数组中的所有元素在内存中的存储方式
上面讨论的二维数组的相关内容都适用于三维数组或更多维的数组。声明一个三维数组: int girl[3][8][5];
可以把一维数组想象成一排女兵,把二维数组想象成一个女兵方阵,把三维数组想象成多个女兵方阵。这样,当你要找其中的一个女兵时,你只要知道她在哪个方阵(从 0、1、2 中选择),在哪一行(从 0-7)中选择,在哪一列(从 0-4 中选择)
切记!数组作为函数的参数传递,不是单纯的值传递,传递的是数组本身。
二维数组作为函数的参数:
#include #include //版本1 指明参数 void print1(int a[3][4]){ for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]); } printf("\n"); } } //版本1 省略一个高维参数 void print2(int a[][4], int lines){ for(int i=0;i } printf("\n"); } } int main(void){ //int arr[3][4]={{},{3,4}}; int a[3][4]={0}; int i=0; int j=0; //给数组成员赋值 for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ a[i][j] = 4*i+j; } } print1(a); print2(a); } |
数组定义时编译器不能确定数组的大小
int a[3][] ; int a[][4] ;
int a[3][]={{1,2},{3,4},{5,6}}
一条原则:仅定义时(无初始化)不能省略,有初始化可以省略高维
严禁数组越界
在使用数组时,要防止数组下标超出边界。也就是说,必须确保下标是有效的值。
int a[10] ; a[10]=100; //错误,访问越界,a[10] 的成员是 a[0] - a[9]
int a[3][4]; a[3][0]=666; //错误, a[3][4] 包含了 3 行 4 列的数组,行下标也是从 0 开始,有效范围 0 - 2
数组(无论几维)传参并不是整个数组的复制
#include #include void fun(int a[3][4]){ for(int i=0;i<3;i++){ for(int j=0;j<4;j++){ a[i][j]=0; } } } int main(void){ //int arr[3][4]={{},{3,4}}; int a[3][4]={0}; int i=0; int j=0; //给数组成员赋值 for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ a[i][j] = 4*i+j; } }
fun(a); //输出 for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]); } printf("\n"); } |
假设下面的数据代表一个 6 x 7 的网格, 加了下划线的网格即为峰点。
5039 5127 5238 5259 5248 5310 5299
5150 5392 5410 5401 5320 5820 5321
5290 5560 5490 5421 5530 5831 5210
5110 5429 5430 5411 5459 5630 5319
4920 5129 4921 5821 4722 4921 5129
5023 5129 4822 4872 4794 4862 4245
假定左上角是[0][0],那么向下移动,则行号加 1;向右移动,则列号加 1, 那么这些峰点的位置就可以描述为:[2][1] [2][5] [4][3]。
位置确定后,与周围 4 个邻节点比较即可确定峰点!(注:网格边界点缺乏 4 个相邻点不计算峰点)地形数据保存于文件中。
算法设计
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- #define N 64
-
- bool isPeak(int map[N][N], int nrows, int ncols)
- {
- if ((map[nrows][ncols] > map[nrows + 1][ncols]) &&
- (map[nrows][ncols] > map[nrows - 1][ncols]) &&
- (map[nrows][ncols] > map[nrows][ncols + 1]) &&
- (map[nrows][ncols] > map[nrows][ncols] - 1))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- int main(void)
- {
- string filename;
- fstream file;
- int map[N][N];
- int ncols, nrows;
-
- cout << "请输入你要打开的文件:";
- cin >> filename;
-
- file.open(filename.c_str());
-
- if (file.fail())
- {
- cerr << "打开文件失败" << endl;
- exit(1);
- }
-
- file >> nrows >> ncols;
- if (nrows > N || ncols > N)
- {
- cerr << "行或列超出指定范围" << endl;
- exit(1);
- }
-
- for (int i = 0; i < nrows; i++)
- {
- for (int j = 0; j < ncols; j++)
- {
- file >> map[i][j];
- }
- }
-
- for (int i = 1; i < nrows-1; i++)
- {
- for (int j = 1; j < ncols-1; j++)
- {
- if (isPeak(map, i, j))
- {
- cout << "行:" << i << "列" << j << "峰值" << map[i][j] << endl;
- }
- }
- }
-
- file.close();
- system("pause");
- return 0;
- }