01.二维数组

一维数组复习

一维数组,点击跳转

二维数组:多个一维数组的集合

格式: 类型名 数组名[常量表达式1][常量表达式2];

通常二维数组中的第一维表示行下标,第二维表示列下标。

行下标和列下标都是从0开始的。

举例:int num [4][6];

相当于一张表,每个表格对应于一个整型变量,下标变化如下表所示:

[0,0]    [0,1]    [0,2]    [0,3]    [0,4]    [0,5]
[1,0]    [1,1]    [1,2]    [1,3]    [1,4]    [1,5]
[2,0]    [2,1]    [2,2]    [2,3]    [2,4]    [2,5]
[3,0]    [3,1]    [3,2]    [3,3]    [3,4]    [3,5]

image

二维数组 num 由4行6列组成,共有24个元素,其中每一行都有6个元素;

如第一行的6个元素是:
num[0][0], num[0][1], num[0][2], num[0][3], num[0][4], num[0][5].

【题目】矩阵数列
给出一个 n*n 的矩阵数列,将该数列存储在二维数组 a 中,并原样输出 (n<10)。

输入样例:

4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

输出样例:

4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
  • 参考程序
#include<iostream>
using namespace std;
int main(){
    int n, a[10][10]; cin>>n;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cin>>a[i][j];
        }
    }
     //输出程序
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}
int 数组长度:(对于普通题目开放的最大值了,具体还需要计算空间大小是否越界)
一维数组 N=1e8;
二维数组 N=2e4;

int 数组空间大小:
一维数组 sizeof(int)*N Byte;
二维数组 sizeof(int)*N*N Byte;

1 T = 1024 G = 2^10 G
1 G = 1024 MB
1 MB = 1024 KB
1 KB = 1024 Byte
1 Byte = 8 bit

生活中我们常见的 U盘存储器,经常会说该U盘的存储容量为 32 G,那么 32 G = 32*1024 MB,然而你却发现真实的容量会少那么一点,是因为厂家生产的时候是按照 10^3 为基数进行生产的,所以到手的 U盘实际容量为 32 G = 32*1000 MB。

二维数组的初始化

全局变量:不在 {} 内的变量

局部变量:在 {} 内的变量

整型全局变量默认初始化为 0。

整型局部变量如果没有赋初值,则会随机化数据;

整型局部变量如果部分赋值,则未赋值部分会初始化为 0。

方式一: int a[N][4]={1,2,3,4,5,6,7};

相当于:  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]=0,
        a[2][0]=0, ...,       a[i][j]=0, ...

方式一:
	1 2 3 4
	5 6 7 0
	0 0 0 0
	0 ... 0

方式二: int a[N][4]={{1,2,3}, {4,5,6}, {7}};

相当于:  a[0][0]=1, a[0][1]=2, a[0][2]=3, a[0][3]=0,
        a[1][0]=4, a[1][1]=5, a[1][2]=6, a[1][3]=0,
        a[2][0]=7, ...,       a[i][j]=0, ...

方式二:
	1 2 3 0
	4 5 6 0
	7 0 0 0
	0 ... 0
#include<iostream>
using namespace std;
int main(){
    int num[4][3] = {{45,6,78}, {43,57,68}, {15,65,72}, {15,47,28}};
    for(int i=0; i<4; i++){
        for(int j=0; j<3; j++)  {
            cout<<num[i][j]<<" "; // 猜猜我会输出什么
        }cout<<endl;
    }
    return 0;
}

二维数组的使用

二维数组的使用与一维数组类似: 数组名[下标1][下标2]

注意:
使用数组时特别注意下标不能越界。

使用二维数组时,区分处理行数据、列数据,还是处理所有数据的行列下标。

一般使用两层循环来控制二维数组,外层控制行数,内层控制列数。

【题目】对角线元素和

输入一个数据 n,接下来输入一个 n*n 方阵,输出方阵对角线的和。

输入样例:

4
1 2 3 4
1 2 3 4
1 2 3 4
4 3 2 1

输出样例:

7 13

【分析】对角线元素和

i j --- i 表示行,j 表示列

00  01  02  03
10  11  12  13
20  21  22  23
30  31  32  33

对角线:有两条,找到对应的规律即可
左上角到右下角:i==j
左下角到右上角:i+j==n-1

int sum1=0,sum2=0;
for(int i=0; i<n; i++){
    for(int j=0; j<n; j++){
        if(i==j)      sum1 += a[i][j];
        if(i+j==n-1)  sum2 += a[i][j];
    }
}
cout<<sum1<<" "<<sum2;
二维数组重点知识:用于地图找规律
i j --- i 表示行,j 表示列

00  01  02  03
10  11  12  13
20  21  22  23
30  31  32  33

依据下标找到规律:
同一行:i 是定值
同一列:j 是定值
左上角到右下角:i-j 是定值
左下角到右上角:i+j 是定值

【题目】图像旋转

输入一个 n 行 m 列的黑白图像的每个像素点灰度,每个元素均在 0~255之间,将它顺时针旋转 90° 后输出(1<=n, m<=100)。

输入样例:

3 3
1 2 3
4 5 6
7 8 9

输出样例:

7 4 1
8 5 2
9 6 3

【分析】图像旋转

将转变前后图像用二维数组下标的形式展示出来,找到规律。
i j --- i 表示行,j 表示列,如:3 行 4 列

旋转前:a[i][j]
00  01  02  03
10  11  12  13
20  21  22  23

旋转后:b[i][j]
20  10  00
21  11  01
22  12  02
23  13  03

程序实现:
#include<iostream>
using namespace std;
const int N=100;
int a[N][N], b[N][N];
int main(){
    int n,m; cin>>n>>m;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>a[i][j];
        }
    }
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            b[i][j] = a[n-1-j][i];
            cout<<b[i][j]<<" ";
        }cout<<endl;
    }
    return 0;
}

【题目】杨辉三角

杨辉三角是一个由数字排列成的三角形数列表,给一个正整数 n,请输出杨辉三角形的前 n 行(n<20)。

输入样例:

7

输出样例:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1

【分析】杨辉三角
杨辉三角的数字是有规律的:

从第 3 行开始,每行第 1 个和最后一个值为 1,其它为其上方和左上方数字和。

设二维数组 a[i][j] 存储坐标为 i-1,列坐标为j-1位置上元素值,则

   a[i][j] = a[i-1][j-1] + a[i-1][j];

每个元素值由其左上方和上方元素求和得到。
因此,可以一行一行的求得元素值。

  • 参考程序
#include<bits/stdc++.h>
using namespace std;
int main() {
    int n, a[20][20]={0}; cin>>n;
    a[1][1]=1;
    for(int i=2; i<=n; i++){
        for(int j=1; j<=n; j++){
            a[i][j] = a[i-1][j]+a[i-1][j-1];
        }
    }
   for(int i=1; i<=n; i++){
        for(int j=1; j<=i; j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

【题目】S形方阵

读入两个数,代表 n 行 m 列,然后从 (0,0) 开始 S 形输出 1~n*m 方阵,如下样例 (0<=n, m<25)。

输入样例:

3 4

输出样例:

    1    2    3    4
    8    7    6    5
    9   10   11   12

【分析】S形方阵
找到每一行的起始位置与终点位置,发现每一行运动结束后方向会发生变化,奇数行从左向右递增,偶数行从右往左递增。

那么可以建立一个二维数组存储答案,设置一个计数器 cnt=0;

每走一格 cnt+1,并存储赋值给当前格子,当一行结束后再逆方向计数;

最后输出二维数组。

const int N=25;
int a[N][N];
int n, m, count=0; cin>>n>>m;
for(int i=0; i<n; i++){
    if(i%2==0){  //如果是偶数行
        for(int j=0; j<m; j++)     a[i][j] = ++count;
    }else{      //如果是奇数行
        for(int j=m-1; j>=0; j--) a[i][j] = ++count;
    }
}

【题目】蛇形方阵

在 n*n 的方阵中填入1,2,3,...,n*n (n<25),要求填成如下形式的蛇形方阵。

每个数据占 5 个宽度。

输入样例:

4

输出样例:

   10   11   12    1
    9   16   13    2
    8   15   14    3
    7    6    5    4

【分析】蛇形方阵
直接输出蛇形方阵是做不到的,如果将数字按蛇形方阵形式存入二维数组中,输出就很容易了。

设二维数组 a[N][N] 存放蛇形方阵,设变量 x 表示行,y 表示列;

那么从 x=1,y=n 开始写入数字 1,然后写入顺序是下、左、上、右。

但是要注意写入时下标不能溢出。

#include<iostream>
#include<iomanip> // setw(5)
using namespace std;
const int N=1e4;
int a[N][N];    //全局变量,数组初始化为 0
int main() {
    int n; cin>>n;
    int x=0, y=n, cnt=0;
    while(cnt<n*n) {
        while(x+1<=n && a[x+1][y]==0) a[++x][y]=++cnt; //向下
        while(y-1>=1 && a[x][y-1]==0) a[x][--y]=++cnt; //向左
        while(x-1>=1 && a[x-1][y]==0) a[--x][y]=++cnt; //向上
        while(y+1<=n && a[x][y+1]==0) a[x][++y]=++cnt; //向右
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            cout<<setw(5)<<a[i][j]; //设置每个数据占 5 个宽度
        } cout<<endl;
    }
    return 0;
}
posted @ 2022-03-20 08:30  HelloHeBin  阅读(708)  评论(0编辑  收藏  举报