我将如何在 C 中反转 2D 数组?

  • 本文关键字:2D 数组 c arrays reverse
  • 更新时间 :
  • 英文 :


假设我的数组看起来像这样。行数将始终与此程序中的列数匹配。

[0] [1] [2]
[3] [4] [5]
[6] [7] [8]

我需要将其转换为相反的形式:

[2] [1] [0]
[5] [4] [3]
[8] [7] [6]

我知道多维数组只是数组的数组,这有望将我的问题范围缩短为反转 1D 数组,但我不知道如何将同样的想法应用于 2D 数组。大小并不总是 3 x 3 数组,但行和列将始终是相同的数字。

尝试以下代码,这里 n 是行数,m 是列数。希望这将解决您的问题。祝您编码愉快!

for(i = 0; i < n; i++) {
for(j = 0; j < m/2; j++) {
int temp = arr[i][j];
arr[i][j] = arr[i][m-j-1];
arr[i][m-j-1] = temp;
}
}

如果你正在寻找一个反转2D数组的函数,那么你可以使用这样的函数声明:void reverse_2d_arr(int , int (*)[]);

哪里

void reverse_2d_arr(int size, int arr[size][size]) {
int i = 0, j, k, temp;
while(i < size) {
j = 0;
k = size - 1;
while(j < k) {
temp = arr[i][j];
arr[i][j] = arr[i][k];
arr[i][k] = temp;
k--;
j++;
}
i++;
}
}

并使用reverse_2d_arr(3, arr);调用它,其中 arr 是您的 2D 数组,3 是它的大小。

使用标准数组

从效率的角度来看,在迭代列值时,每次迭代交换两个元素。由于数组的宽度是固定的,因此从开头和结尾元素开始,交换它们,然后从末端到中间继续工作,例如

void rev2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}

(在..[j]..[k]的上方,每个内循环的迭代都交换

(或者,如果要使用while循环和指向每行中开始和结束元素的指针来执行相同的操作(除了反向迭代行之外(,则可以执行以下操作:

void rev2dptrs (int (*a)[COLS], int rows, int cols)
{
while (rows--) {
int *beg = *(a + rows), *end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}

在每种情况下,例如,如果您有:

#define ROWS 3
#define COLS ROWS
...
int a[][COLS] = {{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }};

您的函数调用将是:

rev2d (a, ROWS, COLS);

或者在第二种情况下:

rev2dptrs (a, ROWS, COLS);

只是正常反转的转折。

使用可变长度数组

最初的目的是避免由于 C11 标准而导致的 VLA 示例 - 6.7.6.2 数组声明符(p4("Variable length arrays are a conditional feature that implementations need not support;"和 C11 标准 - 6.10.8.3 条件功能宏__STDC_NO_VLA__

但是,正如注释中所指出的,并且考虑到几乎所有主要编译器将继续提供VLA的实际实用性,您可以通过反转声明并指定rowscols大小,然后将数组作为VLA传递来提供更大的灵活性。好处是它可以将您从恒定的大小中解放出来。例如,但是可以将数组作为VLA传递的函数重新编写:

void rev2dvla (int rows, int cols, int a[rows][cols])
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}

并带有指针:

void rev2dptrsvla (int rows, int cols, int a[rows][cols])
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}

在这里,好处是您可以摆脱每行元素数的整数常量约束。通过在数组参数之前指定rowscols参数,在将数组int a[rows][cols]指定为允许 VLA 为完整类型的参数之前,rowscols值是已知的。

然后,函数调用将是:

rev2dvla (rows, COLS, a);

rev2dptrsvla (rows, COLS, a);

如果您了解每种方式以及它们与其他方式的不同之处 - 那么您就可以控制对 2D 数组进行排序。如果您有其他问题,请告诉我。

将完整示例放在一起以至少执行上述每个函数一次并添加一个 print2D 函数,您可以执行以下操作:

#include <stdio.h>
#define COLS 3
void rev2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
void rev2dptrs (int (*a)[COLS], int rows, int cols)
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
void rev2dvla (int rows, int cols, int a[rows][cols])
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
void rev2dptrsvla (int rows, int cols, int a[rows][cols])
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
void prn2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
printf (" %2d", a[i][j]);
putchar ('n');
}
}
int main (void) {
int a[][COLS] = {{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }},
rows = sizeof *a / sizeof **a;
puts ("original:");
prn2d (a, rows, COLS);          /* print original */
rev2d (a, rows, COLS);          /* reverse col values using indexes */
puts ("nreversed using indexes:");
prn2d (a, rows, COLS);          /* print reversed array */
rev2dptrs (a, rows, COLS);      /* reverse reversed array to restore original */
puts ("nrestore original using pointers:");
prn2d (a, rows, COLS);          /* print original */
rev2dptrs (a, rows, COLS);      /* reverse col values using pointers */
puts ("nreverse again using pointers:");
prn2d (a, rows, COLS);          /* print reversed array */
rev2dvla (rows, COLS, a);       /* reverse col values restoring original */
puts ("nrestore original using VLA w/indexes:");
prn2d (a, rows, COLS);          /* print original */
rev2dvla (rows, COLS, a);       /* reverse col values using indexes */
puts ("nreversed with VLA using indexes:");
prn2d (a, rows, COLS);          /* print reversed array */
rev2dptrsvla (rows, COLS, a);   /* reverse reversed array to restore original */
puts ("nrestore original using VLA w/pointers:");
prn2d (a, rows, COLS);          /* print original */
rev2dptrsvla (rows, COLS, a);   /* reverse col values using pointers */
puts ("nreverse again using VLA w/pointers:");
prn2d (a, rows, COLS);          /* print reversed array */
}

示例使用/输出

$ ./bin/revarr2d
original:
0  1  2
3  4  5
6  7  8
reversed using indexes:
2  1  0
5  4  3
8  7  6
restore original using pointers:
0  1  2
3  4  5
6  7  8
reverse again using pointers:
2  1  0
5  4  3
8  7  6
restore original using VLA w/indexes:
0  1  2
3  4  5
6  7  8
reversed with VLA using indexes:
2  1  0
5  4  3
8  7  6
restore original using VLA w/pointers:
0  1  2
3  4  5
6  7  8
reverse again using VLA w/pointers:
2  1  0
5  4  3
8  7  6

相关内容

  • 没有找到相关文章

最新更新