lectura de
Este es un repost de uno de los posts mas visitados en el sitio, sobre el algoritmo de matriz en espiral.
He reimplementado el algoritmo de una forma mas simple de atacar, pensando en una funcion fill()
que llena elementos en una matriz de a lineas o columnas.
Por ejemplo si se tiene una matriz de 5x5 inciada con 0s:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
// Llena la matriz en el eje x, en la fila 0,
// desde la columna 1 a la 3
fill(matriz, 'x', 0, 1, 3);
// se obtiene:
0 1 2 3 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Otro ejemplo:
// Llena la matriz en el eje y, en la columna 2,
// desde la fila 2 a la 4
fill(matriz, 'y', 2, 2, 4);
// se obtiene:
0 1 2 3 0
0 0 0 0 0
0 0 4 0 0
0 0 5 0 0
0 0 6 0 0
por último
// Llena la matriz en el eje y, en la columna 0,
// desde la fila 4 a la 1
fill(matriz, 'y', 0, 4, 1);
// se obtiene:
0 1 2 3 0
10 0 0 0 0
9 0 4 0 0
8 0 5 0 0
7 0 6 0 0
De esta forma se puede analizar el patrón de llenar una matriz en espiral, dibujarlo en papel ayuda, el patrón surge al utilizar la función fill()
y observar como cambian los indices. Luego el algoritmo de llenar la matriz en espiral funciona para matrices de NxM (cuadradas y rectangulares). Les dejo la implementación final a continuación:
#include <stdio.h>
#include
#define N 4 /* Define la dimensión máxima de la matriz */
#define M 7 /* Define la dimensión máxima de la matriz */
void show(int matrix[][M]);
void llenar_esperilicamente(int matrix[][M]);
int fill(int matrix[][M], const char axis, const int row, const int start, const int end, int *start_value);
int main(int argc, char *argv[]) {
int matrix[N][M];
llenar_esperilicamente(matrix);
show(matrix);
return 0;
}
/**
* Muestra la matriz entregada por parámetro
* @param matrix matriz a ser mostrada
*/
void show(int matrix[][M]) {
/* imprime la matriz recibida por parámetro en la pantalla */
int i,j;
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++)
printf ("%4d", matrix[i][j]);
printf ("\n");
}
}
/**
* Llena la matriz del parámetro en forma de espiral con números ascendientes
* @param matrix Matriz a ser llenada
*/
void llenar_esperilicamente(int matrix[][M]) {
int current = 1;
int n = N-1;
int m = M-1;
int aux = 0;
do {
fill(matrix, 'x', aux, aux, m - aux, ¤t);
if (current > N*M) break;
fill(matrix, 'y', m - aux, (aux + 1), n - aux, ¤t);
if (current > N*M) break;
fill(matrix, 'x', n - aux, m-(aux + 1), aux, ¤t);
if (current > N*M) break;
fill(matrix, 'y', aux, n-(aux + 1), (aux + 1), ¤t);
aux++;
} while (current < N*M);
}
/**
* Llena en una *matrix* dada desde el punto *start* al *end*
* en algun eje *axis* definido, comenzando con el valor *start_value*
* @param matrix Matriz sobre la que se trabaja
* @param axis eje en que se llena: x o y
* @param j que fila o que columna llenar
* @param start donde comenzar
* @param end donde terminar
* @param start_value puntero al contador
*/
int fill(int matrix[][M], const char axis, const int j, const int start, const int end, int *start_value) {
int i;
int step;
if (start == end) {
if (axis == 'x')
matrix[j][end] = (*start_value)++;
else if (axis == 'y')
matrix[end][j] = (*start_value)++;
return 0;
}
step = start > end ? -1 : 1;
for (i = start; start > end ? i >= end : i <= end; i += step) {
if (axis == 'x')
matrix[j][i] = (*start_value)++;
else if (axis == 'y')
matrix[i][j] = (*start_value)++;
}
return 1;
}
Compilación y ejecución del ejemplo anterior:
$ gcc matrizenespiral.c -o executeme -Wall
$ ./executeme
1 2 3 4 5 6 7
18 19 20 21 22 23 8
17 28 27 26 25 24 9
16 15 14 13 12 11 10