简体   繁体   English

我 go 如何在 C 中反转二维数组?

[英]How would I go about reversing a 2D array in C?

Let's say my array looks like this.假设我的数组看起来像这样。 The number of rows will always match the number of columns in this program.行数将始终与该程序中的列数匹配。

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

I would need to turn this into the reversed form:我需要把它变成相反的形式:

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

I know that multidimensional arrays are just arrays of arrays, which hopefully shortens the scale of my question to just reversing a 1D array, but I don't know how to apply that same idea to a 2D array.我知道多维 arrays 只是 arrays 的 arrays,这有望将我的问题的规模缩短为仅反转一维数组,但我不知道如何将相同的想法应用于二维数组。 The size will not always be a 3 by 3 array, but again the rows and columns will always be the same number.大小不会总是 3 x 3 数组,但行和列也总是相同的数字。

Try following code, here n is the number of rows and m is the number of columns.试试下面的代码,这里 n 是行数,m 是列数。 Hopefully this will solve your problem.希望这能解决您的问题。 Happy coding!编码愉快!

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;
    }
}

If you are looking for a function to reverse 2D array, then you can use a function declaration like this: void reverse_2d_arr(int, int (*)[]);如果您正在寻找 function 来反转二维数组,那么您可以使用 function 声明,如下所示: void reverse_2d_arr(int, int (*)[]);

where,在哪里,

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++;
    }
}

and call it using, reverse_2d_arr(3, arr);并使用reverse_2d_arr(3, arr); where arr is your 2d array and 3 its size.其中 arr 是你的二维数组,它的大小是 3。

Using Standard Arrays使用标准 Arrays

From an efficiency standpoint, swap two-elements per-iteration when iterating over the column values.从效率的角度来看,在迭代列值时每次迭代交换两个元素。 Since your array has a fixed width, start with the beginning and end elements, swap them, and continue working from the end to the middle, eg由于您的数组具有固定宽度,因此从开始和结束元素开始,交换它们,然后从结束到中间继续工作,例如

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;
        }
}

(above the ..[j] and ..[k] elemnts are each swapped per-iteration of the inner-loop) (在..[j]..[k]元素之上,每个元素都在内部循环的每次迭代中交换)

Or if you wanted to do the same thing using while loops and pointers to the beginning and end elements in each row (aside from iterating over the rows in reverse), you could do the following:或者,如果您想使用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;
        }
    }
}

In each case, for example if you had:在每种情况下,例如,如果您有:

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

Your function call would be:您的 function 电话将是:

    rev2d (a, ROWS, COLS);

or in the second case:或者在第二种情况下:

    rev2dptrs (a, ROWS, COLS);

Just a twist on a normal reversal.只是正常逆转的转折。

Using Variable Length Arrays使用可变长度 Arrays

The original intent was to avoid examples with VLA due to C11 Standard - 6.7.6.2 Array declarators(p4) "Variable length arrays are a conditional feature that implementations need not support;"由于C11 标准 - 6.7.6.2 数组声明符(p4) "Variable length arrays are a conditional feature that implementations need not support;"最初的意图是避免使用 VLA 的示例; and C11 Standard - 6.10.8.3 Conditional feature macros __STDC_NO_VLA__C11 标准 - 6.10.8.3 条件特征宏__STDC_NO_VLA__

However as pointed out in the comments, and with the real-world practicality that virtually all major compilers will continue to provide VLA, you can provide a bit more flexibility by reversing the declarations and specifying the rows and cols sizes fist and then passing the array as a VLA.然而,正如评论中所指出的,并且由于现实世界中几乎所有主要编译器都将继续提供 VLA 的实用性,您可以通过反转声明并先指定rowscols大小然后传递数组来提供更多的灵活性作为 VLA。 The benefit is that it frees you from a constant size.好处是它使您摆脱了恒定的大小。 For example, but functions can be re-written passing the array as a 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;
        }
}

and with pointers:并带有指针:

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;
        }
    }
}

Here, the benefit is you are freed from the integer constant constraint on the number of elements per-row.在这里,好处是您可以摆脱每行元素数的 integer 常量约束。 By specifying the rows and cols parameters before the array parameter, the rows and cols values are known before the array int a[rows][cols] is specified as a parameter allowing the VLA to be a complete type.通过在数组参数之前指定rowscols参数,在数组int a[rows][cols]被指定为参数之前已知rowscols值,从而使 VLA 成为完整类型。

The function calls would then be: function 调用将是:

    rev2dvla (rows, COLS, a);

and

    rev2dptrsvla (rows, COLS, a);

If you understand each of the ways and how they differ from the others -- then you have sorting a 2D array under control.如果您了解每种方式以及它们与其他方式的不同之处——那么您就可以控制对二维数组进行排序。 Let me know if you have further questions.如果您还有其他问题,请告诉我。

Putting the full example together to exercise each function above at least once and adding a print2D function, you could do something like the following:将完整的示例放在一起,至少对上面的每个 function 进行一次练习,并添加一个 print2D function,您可以执行如下操作:

#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 */
}

Example Use/Output示例使用/输出

$ ./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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM