关于二维数组处理的统一思想

来源:互联网 发布:银川古装摄影推荐知乎 编辑:程序博客网 时间:2024/06/05 17:56

  • 引言
  • 坐标系
  • 终端编码
  • 思维误区
  • 解决思路
  • 统一标准


引言

在编码中接触过二维数组的人应该都被二维数组的位置各种困扰过,对吧。(没困扰的请 alt+f4 或 cmd+q)

坐标系

这里先来说说坐标系:笛卡尔坐标系,又称右手坐标系。引用一下前辈的介绍吧。

终端编码

为了让一个 n*m 的二维数组在终端中显示出来,我们会写出如下语句:

int matrix[n][m] = { 0 };for(auto i= 0; i != n; ++j) {    for(auto j = 0; j != m; ++j) {        cout << matrix[i][j] << " ";    }    cout << endl;}

这里注意!终端对数据的输出方向是从上至下,从左至右。

这种输出方式与我们一般所见的坐标系在 y 轴方向上是反的。

由此就导致了当我们在程序中试图以笛卡尔坐标系操纵数组时发现结果和我们想的不一样。

思维误区

  • 理所当然的认为二维数组是一个 ↓→ 的样子
  • 想使用笛卡尔坐标系去读取二维数组中的元素

解决思路

二维数组的样子,在内存中的确类似 ↓→,因为,它的地址就是这么排列的

首地址,其值是一个指向一段连续内存的首地址的指针
首地址的下一个地址,其值同上
类推……

所以可以简单的理解为二维数组的第一个下标是行数,二维数组的第二个下标是列数

但是如果不再多想,这里的行列在大脑中依旧是按照终端的顺序,↓→

当我们试图去用笛卡尔坐标系对应转换为这行列时,就得有以下转换:

int convertXToCol(int x) {    return x;}int convertYToRow(int y) {    return n-1-y;}

这样子其实已经有了初步解决方法,即:
对于外部的操作使用笛卡尔坐标系,而对于内部的实现使用的是终端坐标系,这两种坐标之间通过转换函数转换

统一标准

我们试着用一种标准去衡量程序的实现和我们的思想,同时我们还需要思考一个问题,二维数组真的有方向吗?即二维数组必须是 ↓→ 的样子吗?

假设以大脑为主,使用笛卡尔坐标系,那么为了让我们程序在终端的输出也保持思维上的一致,不论在何处转换,总得有一次转换。

期望坐标 -> 程序坐标 -> 终端显示坐标

就在以上过程中无可避免的有一次转换过程。

期望坐标:x,y
程序坐标:matrix[x][y]
终端显示坐标:x,y

二维数组的方向,答案是:没有。
惯性思维所决定二维数组的方向 ↓→ 只是你的遐想,你这样想只是因为终端的输出也保持了平时书写的习惯,即 ↓→ 的形式。

比如有这么一个矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
将它套到笛卡尔坐标系中,发现 (0,0) 点并非最小的数,而是9。

int num = 1;int matrix[3][4];for(auto i = 0; i != 3; ++i) {    for(auto j = 0; j != 4; ++j) {        matrix[i][j] = num++;    }}

依旧照着以上的顺序输出就是上面那个矩阵的样子。
让我们保持和笛卡尔坐标系一致的样子输出。

for(auto i = 3; i != 0; --i) {    for(auto j = 0; j != 4; ++j) {        cout << matrix[i-1][j] << " ";    }    cout << endl;}// 9 10 11 12// 5 6 7 8// 1 2 3 4

试着再用笛卡尔坐标系来访问。

int x = 0;int y = 0;while(cin >> x >> y) {    cout << matrix[y][x] << endl;}

可以看到,编码的时候需要将 y 置于第一个下标,将 x 置于第二个下标才能得到正确的访问结果。
试着将 x 置于第一个下标,y 置于第二个下标,那么以上就得改写成:

int num = 1;const int maxX = 4;const int maxY = 3;int matrix[maxX][maxY];for(auto y = 0; y != maxY; ++y) {    for(auto x = 0; x != maxX; ++x) {        matrix[x][y] = num++;    }}for(auto y = maxY; y != 0; --y) {    for(auto x = 0; x != maxX; ++x) {        cout << matrix[x][y-1] << " ";    }    cout << endl;}int x = 0;int y = 0;while(cin >> x >> y) {    cout << matrix[x][y] << endl;}

可以看到,从赋值开始我们就要将数组以笛卡尔坐标系的方式赋值,只不过在终端显示的时候因为终端打印的方向需要将 y 反过来。

至此,我们处理了一个在思想和编码转换过程中非常无聊的细节


CSDN 辣鸡 MD 编辑器,无序列表格式全丢

原创粉丝点击