簡體   English   中英

我 go 如何在 C 中反轉二維數組?

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

假設我的數組看起來像這樣。 行數將始終與該程序中的列數匹配。

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

我需要把它變成相反的形式:

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

我知道多維 arrays 只是 arrays 的 arrays,這有望將我的問題的規模縮短為僅反轉一維數組,但我不知道如何將相同的想法應用於二維數組。 大小不會總是 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;
    }
}

如果您正在尋找 function 來反轉二維數組,那么您可以使用 function 聲明,如下所示: 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 是你的二維數組,它的大小是 3。

使用標准 Arrays

從效率的角度來看,在迭代列值時每次迭代交換兩個元素。 由於您的數組具有固定寬度,因此從開始和結束元素開始,交換它們,然后從結束到中間繼續工作,例如

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

您的 function 電話將是:

    rev2d (a, ROWS, COLS);

或者在第二種情況下:

    rev2dptrs (a, ROWS, COLS);

只是正常逆轉的轉折。

使用可變長度 Arrays

由於C11 標准 - 6.7.6.2 數組聲明符(p4) "Variable length arrays are a conditional feature that implementations need not support;"最初的意圖是避免使用 VLA 的示例; 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;
        }
    }
}

在這里,好處是您可以擺脫每行元素數的 integer 常量約束。 通過在數組參數之前指定rowscols參數,在數組int a[rows][cols]被指定為參數之前已知rowscols值,從而使 VLA 成為完整類型。

function 調用將是:

    rev2dvla (rows, COLS, a);

    rev2dptrsvla (rows, COLS, a);

如果您了解每種方式以及它們與其他方式的不同之處——那么您就可以控制對二維數組進行排序。 如果您還有其他問題,請告訴我。

將完整的示例放在一起,至少對上面的每個 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 */
}

示例使用/輸出

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