这个简单的代码尝试从索引 [0][0] 以螺旋方式移动 2 x 2 矩阵,直到原始矩阵中没有元素为止。 例如,如果有一个如下所示的矩阵,
[[1 2 3]
[4 5 6]
[7 8 9]]
输出将是,
[1 2 3 6 9 8 7 4 5]
这段代码运行正常,但在最后短暂暂停,然后最终打印输出数组。 造成这种行为的原因是什么?
#include <stdio.h>
#include <stdlib.h>
typedef enum {
move_right,
move_down,
move_left,
move_up
}States;
void print_array(int* arr, int n)
{
for(int i = 0; i<n; i++){
printf(" %d", arr[i]);
}
}
void spiral_matrix(int* input, int row_size, int col_size, int* output)
{
int size = row_size * col_size;
int max_col = col_size-1;
int max_row = row_size-1;
int min_col = 0;
int min_row = 0;
int i = 0;
int j = 0;
States current_state = move_right;
int idx = 0;
while(idx < size) {
switch (current_state)
{
case move_right:
if(j < max_col) {
output[idx] = *(input+i*col_size + j);
j++;
idx++;
} else {
current_state = move_down;
min_row += 1;
}
break;
case move_down:
if(i < max_row) {
output[idx] = *(input+i*col_size + j);
i++;
idx++;
} else {
current_state = move_left;
max_col--;
}
break;
case move_left:
if(j > min_col) {
output[idx] = *(input+i*col_size + j);
j--;
idx++;
} else {
current_state = move_up;
max_row--;
}
break;
case move_up:
if(i > min_row) {
output[idx] = *(input+i*col_size + j);
i--;
idx++;
} else {
current_state = move_right;
min_col += 1;
}
break;
default:
break;
}
}
}
#define N 4
#define M 4
void main(void)
{
int A[N][M] = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}};
int* spiral_out = (int*)malloc(N*M*sizeof(int));
spiral_matrix(A[0], N, M, spiral_out);
print_array(spiral_out, N*M);
free(spiral_out);
}
这段代码运行正常,但在最后短暂暂停,然后最终打印输出数组。造成这种行为的原因是什么?
这只是你的假设,缺少事实。
你的逻辑有问题-
打印第一行
1,2,3,4
时,仅将元素3
写入输出数组,并将current_state
设置为move_down
,在move_down
情况下,将4
写入output
数组。但从逻辑上讲,它应该写入到元素4
,然后将current_state
设置为move_down
。当以螺旋方式遍历时,所有角元素的行为相同。
当到达最后一个元素时,变量
max_col
、max_row
、min_col
、min_row
、i
、j
、idx
的值设置为 while
都不会循环条件导致 false
或 if
循环体中的任何 while
条件导致 true
以及变量 max_col
、max_row
、min_col
和 min_row
的值根据以下条件递增或递减else
块语句。在某一阶段,它们要么上溢/下溢(取决于其是否递增/递减)并最终导致“未定义的行为”。 (未定义的行为包括它可能会错误地执行(崩溃或默默地生成不正确的结果),或者它可能会偶然地完全按照程序员的意图进行操作。)
在 max_col
数组中写入元素
max_row
(螺旋遍历中倒数第二个元素)后,变量 min_col
、min_row
、i
、j
、idx
、11
、output
的值(仅记录了几次迭代):max_col : 1, max_row : 2, min_col : 1, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 1, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 2, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 1, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 3, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : 0, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 4, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -1, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 5, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -2, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -3, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -3, min_col : 6, min_row : 6, i : 2, j : 1, idx : 15
......
......
...... // keep on incrementing/decrementing in same pattern and loop iterates
while
循环不断迭代,给你一种
暂停的印象。 要解决此问题,在更改
current_state
时,根据状态正确设置
i
和 j
: while(idx < size) {
switch (current_state)
{
case move_right:
if(j <= max_col) { // write to array till max column
output[idx] = *(input+i*col_size + j);
j++;
idx++;
} else {
current_state = move_down;
j = max_col; i++; // if moving down, increment row and set column to max
min_row += 1;
}
break;
case move_down:
if(i <= max_row) { // write to array till max row
output[idx] = *(input+i*col_size + j);
i++;
idx++;
} else {
current_state = move_left;
i = max_row; j--; // if moving left, set row to max and decrement column
max_col--;
}
break;
case move_left:
if(j >= min_col) { // write to array till min column
output[idx] = *(input+i*col_size + j);
j--;
idx++;
} else {
current_state = move_up;
j = min_col; i--; // if moving up, set column to min and decrement row
max_row--;
}
break;
case move_up:
if(i >= min_row) { // write to array till min row
output[idx] = *(input+i*col_size + j);
i--;
idx++;
} else {
current_state = move_right;
i = min_row; j++; // if moving right, set row to min and increment column
min_col += 1;
}
break;
default:
break;
}
矩阵的螺旋遍历可以用更好、更简单的方式实现,但是您在问题中提到了术语
state machine
,所以我假设,您有意在代码中包含
current_state
,而这根本不是必需的.