This is the algorithm for traversing a matrix in spiral fashion and printing the traversal as an array in Python:
def spiralTraverse(array):
result = []
startRow, endRow = 0, len(array) - 1
startCol, endCol = 0, len(array[0]) - 1
while startRow <= endRow and startCol <= endCol:
for col in range(startCol, endCol 1):
result.append(array[startRow][col])
for row in range(startRow 1, endRow 1):
result.append(array[row][endCol])
for col in reversed(range(startCol, endCol)):
if startRow == endRow:
break
result.append(array[endRow][col])
for row in reversed(range(startRow 1, endRow)):
if startCol == endCol:
break
result.append(array[row][startCol])
startRow = 1
endRow -= 1
startCol = 1
endCol -= 1
return result
So if sample input is
array = [[1, 2, 3, 4],[12, 13, 14, 5],[11, 16, 15, 6],[10, 9, 8, 7]]
Output will be
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
I am trying to translate this into C with pointers but the function fails to print the final array. The file compiles but with warnings related to the multidimensional array as argument in spiralTraverse().
I call the spiralTraverse function from main() as follows: spiralTraverse(*array[r], r, c)
, where r=rows
and c=cols
are number of rows and columns respectively.
This is what I did:
void spiralTraverse(int *vector[], int rows, int cols)
{
int i, indx_col, indx_row;
int indx_array = 0;
int startRow = 0;
int endRow = rows-1;
int startCol = 0;
int endCol = cols-1;
int new_array[rows*cols];
while ((startRow <= endRow) && (startCol <= endCol))
{
for (indx_col=startCol;indx_col<endCol 1;indx_col )
new_array[indx_array ] = *(*(vector startRow) indx_col);
for (indx_row=startRow 1;indx_row<endRow 1;indx_row )
new_array[indx_array ] = *(*(vector indx_row) endCol);
for (indx_col=endCol;indx_col>startCol;indx_col--)
{
if (startRow == endRow)
break;
new_array[indx_array ] = *(*(vector endRow) indx_col);
}
for (indx_row=endRow;indx_row>startRow 1;indx_row--)
{
if (startCol == endCol)
break;
new_array[indx_array ] = *(*(vector indx_row) startCol);
}
startRow ;
endRow--;
startCol ;
endCol--;
}
puts("");
puts("The array below displays the elements in spiral order");
for (i=0;i<(rows*cols);i )
printf("%d, ", new_array[i]);
puts("");
}
}
Why is the program failing to print my final one-dimensional array?
CodePudding user response:
Function argument
The file compiles but with warnings related to the multidimensional array as argument in
spiralTraverse()
.
Please refer to those others Q&A for details about the proper way to allocate and pass multidimensional arrays as function parameters in C:
Correctly allocating multi-dimensional arrays
What's the point of VLA anyway?
How to pass a multidimensional array to a function in C and C
Given the array
int array[][4] = {
{ 1, 2, 3, 4},
{12, 13, 14, 5},
{11, 16, 15, 6},
{10, 9, 8, 7}
};
The function signature could be one of those
// Declaring m as a Variable Length Array (since C99, optional from C11)
void spiral_traverse(int rows, int cols, int m[rows][cols]);
// or as a pointer to arrays of size 4
void spiral_traverse(int rows, int *m[4]);
Keep It Simple
The C implementation of the algorithm has an issue with the extemes of the loops, in particular the second and the third:
for ( indx_row = startRow 1; indx_row < endRow 1; indx_row )
// ^^^^^^^^^^^^
/* ... */ = *(*(vector indx_row) endCol);
for ( indx_col = endCol; indx_col > startCol; indx_col-- )
// ^^^^^^^^^^^^^^^^^
/* ... */ = *(*(vector endRow) indx_col);
The last element visited by the first (well, second) loop is vector[endRow][endCol]
, which is the same one visited first by the other loop.
The following version produces the expected output.
Note that I changed the extremes of the loops.
#include <stdio.h>
void spiral_traverse(int rows, int cols, int m[rows][cols]);
int main(void)
{
int array[][4] = {
{ 1, 2, 3, 4},
{12, 13, 14, 5},
{11, 16, 15, 6},
{10, 9, 8, 7}
};
spiral_traverse(4, 4, array);
spiral_traverse(3, 4, array); // Elements are stored row-major.
}
void spiral_traverse(int rows, int cols, int m[rows][cols])
{ // m is a Variable Length Array ^^^^^^^^^^^^^^^^^
int startRow = 0;
int endRow = rows - 1;
int startCol = 0;
int endCol = cols - 1;
int new_array[rows*cols]; // <-- Another VLA
int i = 0;
while ((startRow <= endRow) && (startCol <= endCol))
{
for (int col = startCol; col < endCol; col, i)
{ // ^ ^^^^^
new_array[i] = m[startRow][col];
} // ^^^^^^^^^^^^^^^^
for (int row = startRow; row < endRow; row, i)
{ // ^^^^^^^^^^ ^ ^^^^^
new_array[i] = m[row][endCol];
} // ^^^^^^^^^^^^^^
for (int col = endCol; col > startCol; --col, i)
{ // ^^^^^^^^ ^ ^^^^^
new_array[i] = m[endRow][col];
} // ^^^^^^^^^^^^^^
for (int row = endRow; row > startRow; --row, i)
{ // ^^^^^^^^ ^ ^^^^^
new_array[i] = m[row][startCol];
} // ^^^^^^^^^^^^^^^^
startRow ;
endRow--;
startCol ;
endCol--;
}
puts("\nThe array below displays the elements in spiral order");
for (i=0;i<(rows*cols);i )
printf("%d, ", new_array[i]);
putchar('\n');
}
Of course, if the goal is only to print the elements, you don't really need to copy all of them into another array. Also, introducing a function pointer parameter, the function could become more generic (see e.g. here).