給定行數 n、列數 m,生成一個 n×m 矩陣,按順時針螺旋順序填入 1 到 n*m,並打印矩陣。
示例(3×4):
1 2 3 4
10 11 12 5
9 8 7 6
矩陣可視為 min(n,m)/2 層同心矩形。每層按 上→右→下→左 四邊依次填充。
#include
#include
void spiral_print(int rows, int cols) {
if (rows <= 0 || cols <= 0) return;
// 1. 動態分配二維數組
int **matrix = (int **)calloc(rows, sizeof(int *));
for (int i = 0; i < rows; i++)
matrix[i] = (int *)calloc(cols, sizeof(int));
int layer = 0; // 當前層 (0-based)
int num = 1; // 待填入數字
int max_num = rows * cols;
while (num <= max_num) {
int top = layer, bottom = rows - 1 - layer;
int left = layer, right = cols - 1 - layer;
// 上邊:左→右
for (int c = left; c <= right && num <= max_num; c++)
matrix[top][c] = num++;
top++;
// 右邊:上→下
for (int r = top; r <= bottom && num <= max_num; r++)
matrix[r][right] = num++;
right--;
// 下邊:右→左
for (int c = right; c >= left && num <= max_num; c--)
matrix[bottom][c] = num++;
bottom--;
// 左邊:下→上
for (int r = bottom; r >= top && num <= max_num; r--)
matrix[r][left] = num++;
left++;
layer++;
}
// 打印
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++)
printf("%4d", matrix[r][c]);
putchar('\n');
}
// 釋放內存
for (int i = 0; i < rows; i++) free(matrix[i]);
free(matrix);
}
int main() {
int n, m;
printf("請輸入行數 列數: ");
if (scanf("%d %d", &n, &m) == 2)
spiral_print(n, m);
return 0;
}
每完成一圈,四個邊界向內收縮:
top++、bottom--、left++、right--num <= max_num 防止單行/單列矩陣重複填充
int **matrix = calloc(rows, sizeof(int *)); // 行指針數組
for (int i = 0; i < rows; i++)
matrix[i] = calloc(cols, sizeof(int)); // 每行數據區
// 釋放時逆序
for (int i = 0; i < rows; i++) free(matrix[i]);
free(matrix);
注意:這是指針數組模擬二維數組,行內存不連續。若需連續內存,用 int (*matrix)[cols] = malloc(rows * sizeof(*matrix)) (C99 VLA) 或 malloc(rows * cols * sizeof(int)) 手動計算索引。
| 變體 | 修改要點 |
|---|---|
| 逆時針螺旋 | 順序改為:上→左→下→右 |
| 從中心向外 | 計算中心點,層數向外擴展 |
| 不規則矩陣打印 | 同樣邊界收縮邏輯,無需存儲 |
| LeetCode 54/59 | 輸入已有矩陣返回數組 / 生成矩陣 |
num <= max_num 判斷導致回頭覆蓋right = cols - 1 - layer 而非 cols - layer螺旋矩陣是考察邊界控制、循環不變量、動態內存管理的經典題目。掌握「四邊界收縮」模板,能輕鬆應對所有螺旋遍歷變體。工程上注意內存分配/釋放配對、輸入合法性檢查、邊界條件測試(1×N、N×1、1×1、0×0)。