【C++】B2099 矩阵交换行
文章目录
- 💯前言
- 💯题目描述
- 题目描述
- 输入格式
- 输出格式
- 输入输出样例
- 输入 #1
- 输出 #1
- 💯题目分析
- 💯不同解法分析
- 我的做法
- 实现步骤:
- 优点:
- 不足:
- 老师的做法
- 实现步骤:
- 优点:
- 不足:
- 优化与改进
- 优化点:
- 💯小结
💯前言
- 在学习 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
💯题目分析
这道题的核心是实现对矩阵的行交换操作,其解题关键点包括:
-
矩阵的存储:
- 使用二维数组存储 5 × 5 的矩阵。
- 每个元素通过两层循环读取并存入数组。
-
行交换逻辑:
- 根据用户输入的行号 m m m 和 n n n,将第 m m m 行和第 n n n 行的元素逐列交换。
- 使用一个临时变量(
tmp
)作为中转,逐列交换两个行的元素。
-
矩阵的输出:
- 交换完成后,按题目要求的格式输出矩阵。
-
输入校验(可选):
- 检查用户输入的行号是否在合法范围内(1 – 5)。
- 若输入非法,给出提示信息并终止程序。
💯不同解法分析
我的做法
以下是我的实现代码:
#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;
}
实现步骤:
-
矩阵输入:
- 定义一个大小为
5×5
的二维数组arr
。 - 使用嵌套
for
循环将输入的矩阵数据存入数组中。
- 定义一个大小为
-
行交换:
- 使用
for
循环遍历矩阵的每一列,逐列交换第m-1
行和第n-1
行的元素。 - 使用中间变量
temp
进行临时存储,确保数据不被覆盖。
- 使用
-
矩阵输出:
- 再次使用嵌套
for
循环按题目要求的格式输出矩阵。
- 再次使用嵌套
优点:
- 代码清晰简洁,符合题目要求。
- 行交换逻辑直观明了,适合初学者理解。
不足:
- 缺少输入校验:未对用户输入的行号 m , n m, n m,n 进行有效性检查。
- 硬编码矩阵大小:矩阵大小固定为
5×5
,缺乏通用性。 - 优化空间有限:行交换逻辑虽然简单,但仍可进一步封装为函数,提高代码的可读性与复用性。
老师的做法
以下是老师的实现代码:
#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;
}
实现步骤:
与我的做法类似,但存在以下不同之处:
-
将数组
arr
和行号变量r1, r2
定义为全局变量。- 优点:全局变量的定义使得主函数更简洁。
- 缺点:全局变量的使用可能影响代码的模块化和可维护性。
-
对于矩阵输入和输出,老师使用了固定的循环变量
i
和j
。 -
行交换逻辑与我的实现方式基本一致,采用中间变量
tmp
完成逐列交换。
优点:
- 与我的实现类似,逻辑清晰简洁。
- 更贴近 C++ 的传统写法。
不足:
- 全局变量的使用:全局变量虽然简化了代码,但可能导致后续维护问题,尤其在多函数代码中。
- 缺少输入校验:未验证用户输入的行号是否在合法范围内。
优化与改进
结合上述分析,可以对代码进行以下优化:
- 输入校验:确保用户输入的行号合法。若输入非法,输出错误信息并终止程序。
- 封装行交换逻辑:将行交换封装为函数,提升代码的可读性与复用性。
- 避免硬编码:使用常量定义矩阵大小,提高代码的通用性。
- 避免全局变量:将全局变量改为局部变量,提升代码的模块化。
以下是优化后的代码:
#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;
}
优化点:
- 输入校验逻辑确保程序健壮性。
- 行交换逻辑封装为独立函数,提高代码复用性。
- 使用常量定义矩阵大小,避免硬编码。
- 仅使用局部变量,减少全局变量的使用。
💯小结
通过对这道题的详细分析和代码实现的对比,可以看到,每一种实现方式都有其优点与不足。优化后的代码在逻辑清晰性、代码复用性和程序健壮性上得到了显著提升。
二维数组操作是 C++ 学习中的重要部分,理解其核心逻辑并掌握优化技巧,对于提升编程能力至关重要。希望本文能够帮助读者更好地理解和运用这些知识。