輸入 n,輸出 n×n 矩陣,數字 1~n² 按「之」字形(對角線往返)填充。例如 n=5:
1 2 6 7 15 3 5 8 14 16 4 9 13 17 22 10 12 18 21 23 11 19 20 24 25
data[0..n²-1] 存 1~n²。arr。#include <stdio.h>
#include <stdlib.h>
int n;
int *data, *arr; // 動態分配
void Init(void) {
scanf("%d", &n);
data = malloc(n * n * sizeof(int));
arr = malloc(n * n * sizeof(int));
for (int i = 0; i < n * n; ++i) data[i] = i + 1; // 填 1..n²
}
// 反轉 data[b..e] (1-based 索引,內部轉 0-based)
void Rev(int b, int e) {
int *p = data - 1; // 偏移便於直接用 1-based 下標
while (e > b) {
int tmp = p[e]; p[e] = p[b]; p[b] = tmp;
++b; --e;
}
}
// 根據對角線編號決定哪些區間需反轉
void Reverse(void) {
int b = 1, e = 1;
// 上半部:對角線長度 1..n
for (int i = 2; i <= n; ++i) {
b = e + 1;
e += i;
if (i % 2 == 0) Rev(b, e); // 偶數條對角線反轉
}
// 下半部:對角線長度 n-1..1
for (int i = n + 1; i < 2 * n; ++i) {
b = e + 1;
e += 2 * n - i;
if (i % 2 == 0) Rev(b, e);
}
}
// 將 data 按「之」字掃描順序寫入 arr (行優先)
void Arrange(void) {
int r = 0, c = 0;
for (int i = n * n - 1; i >= 0; --i) { // 從 data 末尾取
arr[r * n + c] = data[i];
--r; ++c; // 移動到右上
if (c == n) { c = r + 2; r = n - 1; } // 撞右邊界
else if (r < 0) { r = c; c = 0; } // 撞上邊界
}
// 複製回 data 供輸出
for (int i = 0; i < n * n; ++i) data[i] = arr[i];
}
void Show(void) {
for (int i = 0; i < n * n; ++i) {
printf("%4d ", data[i]);
if ((i + 1) % n == 0) putchar('\n');
}
}
int main(void) {
Init();
Reverse();
Arrange();
Show();
free(data); free(arr);
return 0;
}
data、arr 均為一維動態數組,通過 r*n+c 索引,簡化內存管理。[b, e]。Arrange 中 (r, c) 從右下角開始,沿右上方向移動,邊界反射邏輯完美覆蓋矩陣所有位置。