2010-01-27 27 views
63

Quiero representar una matriz 2D con una matriz 1D. Una función pasará las dos indicaciones (x, y) y el valor para almacenar. Estas dos indicaciones representarían un solo elemento de una matriz 1D y lo configurarían en consecuencia. Sé que la matriz 1D necesita tener el tamaño de arrayWidth × arrayHeight, pero no sé cómo configurar cada elemento.Asignar una matriz 2D a una matriz 1D

Por ejemplo, ¿cómo distingo (2,4,3) de (4,2,3)? Intenté configurar la matriz como x * y, pero 2 * 4 y 4 * 2 daría como resultado el mismo lugar en la matriz y necesito que sean diferentes.

Respuesta

110

Es necesario decidir si los elementos de la matriz se almacenarán en orden de fila o el orden de las columnas y luego sea consecuente al respecto. http://en.wikipedia.org/wiki/Row-major_order

El lenguaje C utiliza orden de fila para matrices multidimensionales

Para simular esto con una sola matriz dimensional, se multiplica el índice de la fila por el ancho y añada el índice de la columna así:

int array[width * height]; 

int SetElement(int row, int col, int value) 
{ 
    array[width * row + col] = value; 
} 
+4

Creo que esta respuesta es más clara, especialmente para los principiantes es mejor no escribir las funciones en una sola línea ... !! Es una mala práctica de todos modos ... :) – Lipis

+2

Esta respuesta también es útil para cuando tienes un compilador (por ejemplo, sistemas integrados) que no tiene multidimensio adecuado nal array support –

+0

Es asombroso cuántas personas pueden responder la misma pregunta correctamente, pero solo UNA de ellas lo dice de una manera que es fácil de entender. Esto es tan simple de una respuesta como se pone. Sin embargo, John es el único que realmente brinda una buena respuesta. Todo lo demás es basura que solo pueden entender fácilmente aquellos que ya conocen la respuesta. Gracias John, por hablar en inglés en lugar de alienígena. Solo sirve para mostrar lo mal que algunas personas están en la enseñanza, y cómo los buenos maestros como John Knoeller saben cómo simplificar y comunicarse de manera mucho más efectiva que los demás. – user2948630

-2

Debería poder acceder a la matriz 2d con un simple puntero en su lugar. El conjunto [x] [y] se organizará en el puntero como p [0x * ancho + 0y] [0x * ancho + 1y] ... [0x * ancho + n-1y] [1x * ancho + 0y] etc.

14

Ejemplo: queremos representar una matriz 2D de tamaño SIZE_X y SIZE_Y. Eso significa que tendremos MAXY filas consecutivas de tamaño MAXX. De ahí que la función de conjunto es

void set_array(int x, int y, int val) { array[ x * SIZE_Y + y ] = val; } 

The Get sería:

int get_array(int x, int y) { return array[ x * SIZE_Y + y ]; } 
+1

Su '' MAXX' y valores MAXY' se nombran a confusión, ya que los valores máximos de 'x' y 'y' son' MAXX - 1' y 'MAXY - 1' respectivamente. Quizás 'SIZE_X' y' SIZE_Y' podrían ser mejores? – caf

+3

[y * maxx + x] es el orden de las columnas, no el orden de las filas. Esta es la forma en que funciona Matlab, pero no es la forma en que las matrices funcionan normalmente en C. –

+0

@John punto válido, @caf también –

1

usando fila importante ejemplo:

A(i,j) = a[i + j*ld]; // where ld is the leading dimension 
         // (commonly same as array dimension in i) 

// matrix like notation using preprocessor hack, allows to hide indexing 
#define A(i,j) A[(i) + (j)*ld] 

double *A = ...; 
size_t ld = ...; 
A(i,j) = ...; 
... = A(j,i); 
12

La fórmula típica para un nuevo cálculo de los índices de matriz 2D en 1D índice de matriz es

index = indexX * arrayWidth + indexY; 

Alternativamente, puede utilizar

index = indexY * arrayHeight + indexX; 

(suponiendo que arrayWidth se mide a lo largo del eje X, y arrayHeight lo largo del eje Y)

Por supuesto, se puede llegar a muchas fórmulas diferentes que proporcionan asignaciones únicas alternativas, pero normalmente no hay necesidad de .

En C/C++ lenguas incorporado en matrices multidimensionales se almacenan en la memoria para que el último índice cambia el más rápido, lo que significa que para una matriz declarada como

int xy[10][10]; 

elemento xy[5][3] es seguida inmediatamente por xy[5][4] en la memoria . Es posible que desee seguir esa convención también, eligiendo una de las dos fórmulas anteriores, según qué índice (X o Y) considere el "último" de los dos.

1

Es importante almacenar los datos de manera que se puedan recuperar en los idiomas utilizados. C-language almacena en orden mayor de fila (todas las primeras filas son las primeras, luego todas las segundas, ...) con cada índice que va de 0 a su dimensión-1. Entonces el orden de la matriz x [2] [3] es x [0] [0], x [0] [1], x [0] [2], x [1] [0], x [1] [ 1], x [1] [2].Entonces, en lenguaje C, x [i] [j] se almacena en el mismo lugar que una entrada de matriz 1-dimensional x1dim [i * 3 + j]. Si los datos se almacenan de esa manera, es fácil de recuperar en lenguaje C.

Fortran y MATLAB son diferentes. Almacenan en orden de columna principal (todas las primeras columnas son las primeras, luego todas las segundas, ...) y cada índice va de 1 a su dimensión. Entonces, el orden de índice es el inverso de C y todos los índices son 1 mayor. Si almacena los datos en el orden de lenguaje C, FORTRAN puede encontrar X_C_language [i] [j] usando X_FORTRAN (j + 1, i + 1). Por ejemplo, X_C_language [1] [2] es igual a X_FORTRAN (3,2). En matrices de 1 dimensión, ese valor de datos está en X1dim_C_language [2 * Cdim2 + 3], que es la misma posición que X1dim_FORTRAN (2 * Fdim1 + 3 + 1). Recuerde que Cdim2 = Fdim1 porque el orden de los índices se invierte.

MATLAB es lo mismo que FORTRAN. Ada es lo mismo que C, excepto que los índices normalmente comienzan en 1. Cualquier idioma tendrá los índices en una de esas órdenes C o FORTRAN y los índices comenzarán en 0 o 1 y se pueden ajustar en consecuencia para obtener los datos almacenados.

Lo siento si esta explicación es confusa, pero creo que es precisa e importante para un programador saber.

6

Como otros han dicho mapas de C en orden de fila

#include <stdio.h> 

    int main(int argc, char **argv) { 
    int i, j, k; 
    int arr[5][3]; 
    int *arr2 = (int*)arr; 

     for (k=0; k<15; k++) { 
      arr2[k] = k; 
      printf("arr[%d] = %2d\n", k, arr2[k]); 
     } 

     for (i=0; i<5; i++) { 
     for (j=0; j< 3; j++) { 
      printf("arr2[%d][%d] = %2d\n", i, j ,arr[i][j]); 
     } 
     } 
    } 

Salida:

arr[0] = 0 
arr[1] = 1 
arr[2] = 2 
arr[3] = 3 
arr[4] = 4 
arr[5] = 5 
arr[6] = 6 
arr[7] = 7 
arr[8] = 8 
arr[9] = 9 
arr[10] = 10 
arr[11] = 11 
arr[12] = 12 
arr[13] = 13 
arr[14] = 14 
arr2[0][0] = 0 
arr2[0][1] = 1 
arr2[0][2] = 2 
arr2[1][0] = 3 
arr2[1][1] = 4 
arr2[1][2] = 5 
arr2[2][0] = 6 
arr2[2][1] = 7 
arr2[2][2] = 8 
arr2[3][0] = 9 
arr2[3][1] = 10 
arr2[3][2] = 11 
arr2[4][0] = 12 
arr2[4][1] = 13 
arr2[4][2] = 14 
Cuestiones relacionadas