Matriz bidimensional dinámica de puntero a puntero

Primer contador de tiempo en este sitio web, así que aquí va …

Soy un novato en C ++ y actualmente estoy trabajando en el libro “Estructuras de datos usando C ++ 2nd ed, de DS Malik”.

En el libro, Malik ofrece dos formas de crear una matriz bidimensional dinámica. En el primer método, declaras que una variable es una matriz de punteros, donde cada puntero es de tipo entero. ex.

int *board[4]; 

..y luego use un for-loop para crear las ‘columnas’ mientras utiliza la matriz de punteros como ‘filas’.

El segundo método, usa un puntero a un puntero.

 int **board; board = new int* [10]; 

etc.

Mi pregunta es esta: ¿cuál es el mejor método? El método ** es más fácil de visualizar, pero el primer método se puede usar de la misma manera. Ambas formas se pueden usar para crear matrices dinámicas de 2 d.

Editar: No fue lo suficientemente claro con la publicación anterior. Aquí hay un código que probé:

 int row, col; cout <> row; cout <> col; int *p_board[row]; for (int i=0; i < row; i++) p_board[i] = new int[col]; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_board[i][j] = j; cout << p_board[i][j] << " "; } cout << endl; } cout << endl << endl; int **p_p_board; p_p_board = new int* [row]; for (int i=0; i < row; i++) p_p_board[i] = new int[col]; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_p_board[i][j] = j; cout << p_p_board[i][j] << " "; } cout << endl; } 

El primer método no se puede usar para crear matrices 2D dinámicas porque al hacerlo:

 int *board[4]; 

esencialmente asignó una matriz de 4 punteros a int en la stack . Por lo tanto, si ahora llena cada uno de estos 4 punteros con una matriz dinámica:

 for (int i = 0; i < 4; ++i) { board[i] = new int[10]; } 

con lo que termina es una matriz 2D con número estático de filas (en este caso 4) y número dynamic de columnas (en este caso 10). Por lo tanto, no es completamente dynamic porque cuando asigna una matriz en la stack debe especificar un tamaño constante , es decir, conocido en tiempo de comstackción . La matriz dinámica se denomina dinámica porque no es necesario conocer su tamaño en tiempo de comstackción , pero puede ser determinado por alguna variable en tiempo de ejecución .

Una vez más, cuando lo haces:

 int *board[4]; 

o:

 const int x = 4; // <--- `const` qualifier is absolutely needed in this case! int *board[x]; 

usted suministra una constante conocida en tiempo de comstackción (en este caso 4 o x ) para que el comstackdor pueda preasignar esta memoria para su matriz, y cuando su progtwig se carga en la memoria ya tendría esta cantidad de memoria para el board matriz, es por eso que se llama estática , es decir, porque el tamaño está codificado y no se puede cambiar dinámicamente (en tiempo de ejecución).

Por otro lado, cuando lo haces:

 int **board; board = new int*[10]; 

o:

 int x = 10; // <--- Notice that it does not have to be `const` anymore! int **board; board = new int*[x]; 

el comstackdor no sabe cuánto requerirá la matriz de la board memoria y, por lo tanto, no asigna previamente nada. Pero cuando inicie su progtwig, el tamaño de la matriz estará determinado por el valor de la variable x (en tiempo de ejecución) y el espacio correspondiente para la matriz de la board se asignará en el denominado montón , el área de memoria donde todos los progtwigs que se ejecutan en su la computadora puede asignar memoria previa desconocida (en tiempo de comstackción) para uso personal.

Como resultado, para crear realmente una matriz dinámica en 2D tienes que ir con el segundo método:

 int **board; board = new int*[10]; // dynamic array (size 10) of pointers to int for (int i = 0; i < 10; ++i) { board[i] = new int[10]; // each i-th pointer is now pointing to dynamic array (size 10) of actual int values } 

Acabamos de crear una matriz cuadrada 2D con 10 por 10 dimensiones. Para recorrerlo y poblarlo con valores reales, por ejemplo 1, podríamos usar bucles nesteds:

 for (int i = 0; i < 10; ++i) { // for each row for (int j = 0; j < 10; ++j) { // for each column board[i][j] = 1; } } 

Lo que describes para el segundo método solo te da una matriz 1D:

 int *board = new int[10]; 

Esto solo asigna una matriz con 10 elementos. Quizás quisiste decir algo como esto:

 int **board = new int*[4]; for (int i = 0; i < 4; i++) { board[i] = new int[10]; } 

En este caso, asignamos 4 int* sy luego hacemos que cada uno de ellos apunte a una matriz dinámicamente asignada de 10 int s.

Entonces ahora estamos comparando eso con int* board[4]; . La principal diferencia es que cuando utiliza una matriz como esta, debe conocerse el número de "filas" en tiempo de comstackción. Esto se debe a que las matrices deben tener tamaños fijos en tiempo de comstackción. También puede tener un problema si desea quizás devolver esta matriz de int* s, ya que la matriz se destruirá al final de su scope.

El método donde tanto las filas como las columnas se asignan dinámicamente requiere medidas más complicadas para evitar memory leaks. Debes desasignar la memoria así:

 for (int i = 0; i < 4; i++) { delete[] board[i]; } delete[] board; 

Debo recomendar el uso de un contenedor estándar en su lugar. Puede usar std::array 4> o quizás un std::vector> que inicie con el tamaño apropiado.

En ambos casos, su dimensión interna puede ser especificada dinámicamente (es decir, tomada de una variable), pero la diferencia está en la dimensión externa.

Esta pregunta es básicamente equivalente a lo siguiente:

Es int* x = new int[4]; “mejor” que int x[4] ?

La respuesta es: ” no , a menos que tenga que elegir esa dimensión de matriz dinámicamente”.

Este código funciona bien con muy pocos requisitos en bibliotecas externas y muestra un uso básico de int **array .

Esta respuesta muestra que cada matriz tiene un tamaño dynamic, así como también la forma de asignar una matriz de hojas de tamaño dynamic a la matriz de twigs de tamaño dynamic.

Este progtwig toma argumentos de STDIN en el siguiente formato:

 2 2 3 1 5 4 5 1 2 8 9 3 0 1 1 3 

Código para el progtwig a continuación …

 #include  int main() { int **array_of_arrays; int num_arrays, num_queries; num_arrays = num_queries = 0; std::cin >> num_arrays >> num_queries; //std::cout << num_arrays << " " << num_queries; //Process the Arrays array_of_arrays = new int*[num_arrays]; int size_current_array = 0; for (int i = 0; i < num_arrays; i++) { std::cin >> size_current_array; int *tmp_array = new int[size_current_array]; for (int j = 0; j < size_current_array; j++) { int tmp = 0; std::cin >> tmp; tmp_array[j] = tmp; } array_of_arrays[i] = tmp_array; } //Process the Queries int x, y; x = y = 0; for (int q = 0; q < num_queries; q++) { std::cin >> x >> y; //std::cout << "Current x & y: " << x << ", " << y << "\n"; std::cout << array_of_arrays[x][y] << "\n"; } return 0; } 

Es una implementación muy simple de int main y se basa únicamente en std::cin y std::cout . Barebones, pero lo suficientemente bueno como para mostrar cómo trabajar con arreglos multidimensionales simples.