C语言状态机实现螺旋矩阵代码为何最后短暂停顿?
螺旋遍历矩阵代码最后阶段停顿的原因分析
该代码实现了从矩阵[0][0]开始的螺旋遍历(例如3×3矩阵:
[[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); }
停顿原因
核心问题在于最后一个元素的处理逻辑存在无意义的循环空转:
当前代码的逻辑是:在每个移动方向的分支中,只有处于"可以继续移动"的条件下,才会将当前元素写入输出数组并推进索引;当到达边界时,仅切换移动状态、调整边界,不处理当前位置的元素。
当遍历到最后一个元素时,该元素恰好处于边界切换的节点上。此时代码会反复切换状态、调整边界,却不执行赋值操作,直到多轮循环后,状态和边界的组合刚好满足"可以继续移动"的条件,才会处理最后一个元素并退出循环。这期间的空转循环会消耗少量时间,表现为短暂停顿。
以4×4矩阵为例:当idx走到15(总元素数16,最后一个元素索引为15)时,i和j停在矩阵中心位置,此时代码会依次切换move_right→move_down→move_left→move_up→move_right,多次调整边界后,才会触发赋值逻辑,完成最后一个元素的处理。
修复方案
调整每个状态分支的逻辑,先处理当前元素,再判断是否继续移动,避免边界切换时遗漏元素导致空转:
修改后的核心逻辑示例(以move_right分支为例,其余分支同理):
case move_right: // 先写入当前元素 output[idx] = *(input+i*col_size + j); idx++; // 再判断是否继续移动 if(j < max_col) { j++; } else { current_state = move_down; min_row += 1; } break;
修改后每个元素都会被及时处理,不会出现无意义的循环空转,停顿现象也会消失。
内容的提问来源于Stack Exchange,提问作者Kyuhyong You
相关产品推荐
相关产品推荐

