自学内容网 自学内容网

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)!