C语言/C++二维数组螺旋输出(zznu)⭐⭐⭐
题目描述(难度⭐⭐⭐)
给定一个 N×M 的二维数组,按顺时针螺旋顺序输出数组中的各个元素。
输入
首先输入两个整数N和M表示二维数组的大小,0<N<100,0<M<100。 接下来输入一个二维数组。输入有N行,每行有M个整数,整数之间空格隔开。
输出
按照顺时针螺旋顺序输出二维数组中的各个元素,每个元素后有一个空格,输出占一行。
样例
输入
3 3
1 2 3
4 5 6
7 8 9
输出
1 2 3 6 9 8 7 4 5
输入
4 1
1
2
3
4
输出
1 2 3 4
本题思路:通过维护四个边界和方向标志,按螺旋顺序遍历并输出二维数组中的元素。
本题难点在于输出边界更新和输出方向更新
本题总论:这是一道经典的模拟类题目,就是先模拟问题解决过程,然后用代码实现
代码1详解
代码结构
1. 读取输入:
◦ 使用 scanf 读取二维数组的行数 a 和列数 b。
◦ 声明一个二维数组 arr,大小为 a 行 b 列。
2. 初始化边界标记:
◦ aa1 和 aa2 分别标记二维数组的上边界和下边界。
◦ bb1 和 bb2 分别标记二维数组的左边界和右边界。
3. 初始化方向标记:
◦ flag1、flag2、flag3 和 flag4 分别标记从左到右、从上到下、从右到左和从下到上的输出方向。
4. 螺旋输出:
◦ 使用 while 循环,直到所有元素都被输出。
◦ 根据当前的输出方向(由 flag1、flag2、flag3 和 flag4 决定),依次输出数组的元素,并更新边界标记。
◦ 每输出一个元素,coter 计数器减 1,当 coter 为 0 时,表示所有元素都已输出,退出循环。
详细步骤
1. 从左到右输出:
◦ 固定行 aa1,列从 bb1 到 bb2。
◦ 更新上边界 aa1,使其向下移动一行。
◦ 切换到从上到下的输出方向。
2. 从上到下输出:
◦ 固定列 bb2,行从 aa1 到 aa2。
◦ 更新右边界 bb2,使其向左移动一列。
◦ 切换到从右到左的输出方向。
3. 从右到左输出:
◦ 固定行 aa2,列从 bb2 到 bb1。
◦ 更新下边界 aa2,使其向上移动一行。
◦ 切换到从下到上的输出方向。
4. 从下到上输出:
◦ 固定列 bb1,行从 aa2 到 aa1。
◦ 更新左边界 bb1,使其向右移动一列。
◦ 切换到从左到右的输出方向。
代码一(时间复杂度是 O(n * m),其中 n 是二维数组的行数,m 是二维数组的列数。)
C语言版
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
/*
%%%%%%%%%%%%%%
/\_/\ /\_/\
(* . *)(+ . +)
> # < > $ <
%%%%%%%%%%%%%%
*/
int main() {
int a, b; // a 表示行数,b 表示列数
scanf("%d%d", &a, &b);
int arr[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
scanf("%d", &arr[i][j]);
}
}
int aa1 = 0, aa2 = a - 1; // aa1 标记二维数组的上边界,aa2 标记二维数组的下边界
int bb1 = 0, bb2 = b - 1; // bb1 标记二维数组的左边界,bb2 标记二维数组的右边界
int flag1 = 1, flag2 = 0, flag3 = 0, flag4 = 0;
// flag1 标记从左向右输出,flag2 标记从上往下输出,flag3 标记从右往左输出,flag4 标记从下往上输出
int coter = a * b; // counter
while (1) { // 无限循环,直到输出所有元素
if (flag1) { // 从左往右输出,行不变,列移动
for (int i = bb1; i <= bb2; i++) {
printf("%d ", arr[aa1][i]);
coter--;
}
if(coter==0) break;//输出所有元素跳出循环
aa1++; // 上边界下降
flag1 = 0; flag2 = 1; // 切换到从上到下
}
if (flag2) { // 从上往下输出,列不变,行移动
for (int i = aa1; i <= aa2; i++) {
printf("%d ", arr[i][bb2]);
coter--;
}
if(coter==0) break;//输出所有元素跳出循环
bb2--; // 右边界往左移动
flag2 = 0; flag3 = 1; // 切换到从右到左
}
if (flag3) { // 从右往左输出,行不变,列移动
for (int i = bb2; i >= bb1; i--) {
printf("%d ", arr[aa2][i]);
coter--;
}
if(coter==0) break;//输出所有元素跳出循环
aa2--; // 下边界上升
flag3 = 0; flag4 = 1; // 切换到从下到上
}
if (flag4) { // 从下往上输出,列不变,行移动
for (int i = aa2; i >= aa1; i--) {
printf("%d ", arr[i][bb1]);
coter--;
}
if(coter==0) break;//输出所有元素跳出循环
bb1++; // 左边界往右移动
flag4 = 0; flag1 = 1; // 切换到从左到右
}
}
return 0;
}
代码二(只是将相关变量名称改变,达到见名知意的效果,思路同上)
初始化边界:
◦ top:上边界,初始值为 0。
◦ bottom:下边界,初始值为 rows - 1。
◦ left:左边界,初始值为 0。
◦ right:右边界,初始值为 cols - 1。
◦ direction:方向标志,初始值为 0,表示从左到右。
·方向标志 0: 从左到右, 1: 从上到下, 2: 从右到左, 3: 从下到上
方向处理:
◦ 从左到右:
■ 遍历从 left 到 right 的所有列,输出 top 行的元素。
■ 更新上边界 top,使其向下移动一行。
■ 更新方向标志 direction,切换到下一个方向(从上到下)。
◦ 从上到下:
■ 遍历从 top 到 bottom 的所有行,输出 right 列的元素。
■ 更新右边界 right,使其向左移动一列。
■ 更新方向标志 direction,切换到下一个方向(从右到左)。
◦ 从右到左:
■ 遍历从 right 到 left 的所有列,输出 bottom 行的元素。
■ 更新下边界 bottom,使其向上移动一行。
■ 更新方向标志 direction,切换到下一个方向(从下到上)。
◦ 从下到上:
■ 遍历从 bottom 到 top 的所有行,输出 left 列的元素。
■ 更新左边界 left,使其向右移动一列。
■ 更新方向标志 direction,切换到下一个方向(从左到右)。
#include <stdio.h>
/*
%%%%%%%%%%%%%%
/\_/\ /\_/\
(* . *)(+ . +)
> # < > $ <
%%%%%%%%%%%%%%
*/
int main() {
int rows, cols; // rows 表示行数,cols 表示列数
scanf("%d %d", &rows, &cols);
int matrix[rows][cols];
// 读取矩阵元素
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &matrix[i][j]);
}
}
// 初始化边界
int top = 0; // 上边界
int bottom = rows - 1; // 下边界
int left = 0; // 左边界
int right = cols - 1; // 右边界
// 初始化方向标志
int direction = 0; // 0: 从左到右, 1: 从上到下, 2: 从右到左, 3: 从下到上
int counter=rows*cols;
// 螺旋输出矩阵元素
while (1) {
if (direction == 0) { // 从左到右
for (int col = left; col <= right; col++) {
printf("%d ", matrix[top][col]);
counter--;
}
if(counter==0) break;
top++; // 上边界下移
direction = 1; // 切换方向
}
if (direction == 1) { // 从上到下
for (int row = top; row <= bottom; row++) {
printf("%d ", matrix[row][right]);
counter--;
}
if(counter==0) break;
right--; // 右边界左移
direction = 2; // 切换方向
}
if (direction == 2) { // 从右到左
for (int col = right; col >= left; col--) {
printf("%d ", matrix[bottom][col]);
counter--;
}
if(counter==0) break;
bottom--; // 下边界上移
direction = 3; // 切换方向
}
if (direction == 3) { // 从下到上
for (int row = bottom; row >= top; row--) {
printf("%d ", matrix[row][left]);
counter--;
}
if(counter==0) break;
left++; // 左边界右移
direction = 0; // 切换方向
}
}
return 0;
}
C++版
#include <iostream>
using namespace std;
int main() {
int a, b; // a 表示行数,b 表示列数
cin >> a >> b;
int arr[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
cin >> arr[i][j];
}
}
int aa1 = 0, aa2 = a - 1; // aa1 标记二维数组的上边界,aa2 标记二维数组的下边界
int bb1 = 0, bb2 = b - 1; // bb1 标记二维数组的左边界,bb2 标记二维数组的右边界
int flag1 = 1, flag2 = 0, flag3 = 0, flag4 = 0;
// flag1 标记从左向右输出,flag2 标记从上往下输出,flag3 标记从右往左输出,flag4 标记从下往上输出
int counter = a * b; // counter
while (1) { // 无限循环,直到输出所有元素
if (flag1) { // 从左往右输出,行不变,列移动
for (int i = bb1; i <= bb2; i++) {
cout << arr[aa1][i] << " ";
counter--;
}
if (counter == 0) break; // 输出所有元素跳出循环
aa1++; // 上边界下降
flag1 = 0; flag2 = 1; // 切换到从上到下
}
if (flag2) { // 从上往下输出,列不变,行移动
for (int i = aa1; i <= aa2; i++) {
cout << arr[i][bb2] << " ";
counter--;
}
if (counter == 0) break; // 输出所有元素跳出循环
bb2--; // 右边界往左移动
flag2 = 0; flag3 = 1; // 切换到从右到左
}
if (flag3) { // 从右往左输出,行不变,列移动
for (int i = bb2; i >= bb1; i--) {
cout << arr[aa2][i] << " ";
counter--;
}
if (counter == 0) break; // 输出所有元素跳出循环
aa2--; // 下边界上升
flag3 = 0; flag4 = 1; // 切换到从下到上
}
if (flag4) { // 从下往上输出,列不变,行移动
for (int i = aa2; i >= aa1; i--) {
cout << arr[i][bb1] << " ";
counter--;
}
if (counter == 0) break; // 输出所有元素跳出循环
bb1++; // 左边界往右移动
flag4 = 0; flag1 = 1; // 切换到从左到右
}
}
return 0;
}
原文地址:https://blog.csdn.net/2401_88591507/article/details/145183114
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!