【C++】B2099 矩阵交换行



博客主页:[小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C++


文章目录



💯前言

  • 在学习 C++ 的过程中,二维数组操作是一个重要的知识点,而矩阵的行交换问题则是一个经典案例。本文将围绕一道涉及矩阵行交换的题目展开,从题目描述到代码实现,再到优化与拓展,逐步解析这道题的核心思想与实现方式。通过分析不同实现方法的优缺点,本文旨在帮助读者更加全面地理解二维数组操作的精髓。
    C++ 参考手册

💯题目描述

题目编号为 B2099 矩阵交换行,具体内容如下:
B2099 矩阵交换行

题目描述

给定一个 5 × 5 的矩阵(数学上,一个 r × c r × c r×c 的矩阵是一个由 r r r 行 c c c 列元素排列成的矩形数组),将第 n n n 行和第 m m m 行交换,输出交换后的结果。

输入格式

输入共 6 行,前 5 行为矩阵的每一行元素,元素与元素之间以一个空格分开。

第 6 行包含两个整数 m , n m, n m,n,以一个空格分开( 1 ≤ m , n ≤ 5 1 \leq m, n \leq 5 1≤m,n≤5)。

输出格式

输出交换之后的矩阵,矩阵的每一行元素占一行,元素之间以一个空格分开。

输入输出样例

输入 #1

1 2 3 4 5
6 7 8 9 0
9 0 3 0 3
4 5 6 7 8
1 2 3 4 5
1 3

输出 #1

9 0 3 0 3
6 7 8 9 0
1 2 3 4 5
4 5 6 7 8
1 2 3 4 5

💯题目分析

这道题的核心是实现对矩阵的行交换操作,其解题关键点包括:

  1. 矩阵的存储:

    • 使用二维数组存储 5 × 5 的矩阵。
    • 每个元素通过两层循环读取并存入数组。
  2. 行交换逻辑:

    • 根据用户输入的行号 m m m 和 n n n,将第 m m m 行和第 n n n 行的元素逐列交换。
    • 使用一个临时变量(tmp)作为中转,逐列交换两个行的元素。
  3. 矩阵的输出:

    • 交换完成后,按题目要求的格式输出矩阵。
  4. 输入校验(可选):

    • 检查用户输入的行号是否在合法范围内(1 -- 5)。
    • 若输入非法,给出提示信息并终止程序。

💯不同解法分析

我的做法

以下是我的实现代码:

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int arr[5][5];
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 5; j++)
        {
            cin >> arr[i][j];
        }
    }
    
    int m, n;
    cin >> m >> n;
    
    for(int j = 0; j < 5; j++)
    {
        int temp = arr[m - 1][j];
        arr[m - 1][j] = arr[n - 1][j];
        arr[n - 1][j] = temp;
    }

    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 5; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }    
    
    return 0;    
}

实现步骤:

  1. 矩阵输入:

    • 定义一个大小为 5×5 的二维数组 arr
    • 使用嵌套 for 循环将输入的矩阵数据存入数组中。
  2. 行交换:

    • 使用 for 循环遍历矩阵的每一列,逐列交换第 m-1 行和第 n-1 行的元素。
    • 使用中间变量 temp 进行临时存储,确保数据不被覆盖。
  3. 矩阵输出:

    • 再次使用嵌套 for 循环按题目要求的格式输出矩阵。

优点:

  • 代码清晰简洁,符合题目要求。
  • 行交换逻辑直观明了,适合初学者理解。

不足:

  1. 缺少输入校验:未对用户输入的行号 m , n m, n m,n 进行有效性检查。
  2. 硬编码矩阵大小:矩阵大小固定为 5×5,缺乏通用性。
  3. 优化空间有限:行交换逻辑虽然简单,但仍可进一步封装为函数,提高代码的可读性与复用性。

老师的做法

以下是老师的实现代码:

cpp 复制代码
#include <iostream>
using namespace std;

int arr[5][5];
int r1, r2;

int main()
{
    int i = 0;
    int j = 0;

    // 输入
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
            cin >> arr[i][j];
        }
    }

    cin >> r1 >> r2;

    // 交换
    for (i = 0; i < 5; i++)
    {
        int tmp = arr[r1 - 1][i];
        arr[r1 - 1][i] = arr[r2 - 1][i];
        arr[r2 - 1][i] = tmp;
    }

    // 输出
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

实现步骤:

与我的做法类似,但存在以下不同之处:

  1. 将数组 arr 和行号变量 r1, r2 定义为全局变量。

    • 优点:全局变量的定义使得主函数更简洁。
    • 缺点:全局变量的使用可能影响代码的模块化和可维护性。
  2. 对于矩阵输入和输出,老师使用了固定的循环变量 ij

  3. 行交换逻辑与我的实现方式基本一致,采用中间变量 tmp 完成逐列交换。

优点:

  • 与我的实现类似,逻辑清晰简洁。
  • 更贴近 C++ 的传统写法。

不足:

  1. 全局变量的使用:全局变量虽然简化了代码,但可能导致后续维护问题,尤其在多函数代码中。
  2. 缺少输入校验:未验证用户输入的行号是否在合法范围内。

优化与改进

结合上述分析,可以对代码进行以下优化:

  1. 输入校验:确保用户输入的行号合法。若输入非法,输出错误信息并终止程序。
  2. 封装行交换逻辑:将行交换封装为函数,提升代码的可读性与复用性。
  3. 避免硬编码:使用常量定义矩阵大小,提高代码的通用性。
  4. 避免全局变量:将全局变量改为局部变量,提升代码的模块化。

以下是优化后的代码:

cpp 复制代码
#include <iostream>
using namespace std;

const int SIZE = 5; // 定义常量矩阵大小

void swapRows(int arr[SIZE][SIZE], int r1, int r2) {
    for (int i = 0; i < SIZE; i++) {
        int tmp = arr[r1][i];
        arr[r1][i] = arr[r2][i];
        arr[r2][i] = tmp;
    }
}

int main() {
    int arr[SIZE][SIZE]; // 定义局部变量
    int r1, r2;

    // 输入矩阵
    for (int i = 0; i < SIZE; i++) {
        for (int j = 0; j < SIZE; j++) {
            cin >> arr[i][j];
        }
    }

    // 输入行号并校验
    cin >> r1 >> r2;
    if (r1 < 1 || r1 > SIZE || r2 < 1 || r2 > SIZE) {
        cout << "Invalid row numbers" << endl;
        return 1; // 错误退出
    }

    // 如果两行相同,无需交换
    if (r1 != r2) {
        swapRows(arr, r1 - 1, r2 - 1);
    }

    // 输出矩阵
    for (int i = 0; i < SIZE; i++) {
        for (int j = 0; j < SIZE; j++) {
            if (j > 0) cout << " "; // 控制空格输出
            cout << arr[i][j];
        }
        cout << endl;
    }

    return 0;
}

优化点:

  1. 输入校验逻辑确保程序健壮性。
  2. 行交换逻辑封装为独立函数,提高代码复用性。
  3. 使用常量定义矩阵大小,避免硬编码。
  4. 仅使用局部变量,减少全局变量的使用。

💯小结

通过对这道题的详细分析和代码实现的对比,可以看到,每一种实现方式都有其优点与不足。优化后的代码在逻辑清晰性、代码复用性和程序健壮性上得到了显著提升。

二维数组操作是 C++ 学习中的重要部分,理解其核心逻辑并掌握优化技巧,对于提升编程能力至关重要。希望本文能够帮助读者更好地理解和运用这些知识。



相关推荐
yky1891 天前
通用指针void*转换为函数指针时强制转换
c++·算法·c·强制类型转换·通用函数指针
JaneZJW2 天前
嵌入式岗位面试八股文(篇三 操作系统(下))
linux·stm32·面试·嵌入式·c
学习前端的小z4 天前
【C++】B2101 计算矩阵边缘元素之和
c
学习前端的小z4 天前
【C++】P1428 小鱼比可爱
c
学习前端的小z4 天前
【C++】图像模糊处理题目详解与实现
c
学习前端的小z5 天前
【C++】深入理解C语言中的特殊字符处理与问题分析优化
c
XLYcmy6 天前
分布式练手:Client
c++·windows·分布式·网络安全·操作系统·c·实验源码
XLYcmy6 天前
分布式练手:Server
c++·windows·分布式·网络安全·操作系统·c·实验源码
学习前端的小z7 天前
【C++】B2089 数组逆序重存放
c