
在java编程中,二维数组(或矩阵)是常见的数据结构,广泛应用于图像处理、游戏开发和科学计算等领域。本教程将引导读者完成从用户输入创建二维数组,到正确显示其内容,并最终实现90度顺时针旋转的整个过程。我们将重点解决在处理用户输入和矩阵旋转时可能遇到的常见问题,特别是如何正确处理非方形矩阵的旋转。
1. 2D 数组的创建与用户输入
创建二维数组并从用户那里获取输入是处理矩阵数据的第一步。我们需要动态地根据用户提供的行数和列数来定义数组的大小。
import java.util.Scanner;
public class MatrixOperations {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入矩阵的行数 (m): ");
int m = sc.nextInt(); // 获取行数
System.out.print("请输入矩阵的列数 (n): ");
int n = sc.nextInt(); // 获取列数
// 声明并初始化二维数组
int[][] array = new int[m][n];
System.out.println("请输入矩阵的元素:");
// 使用嵌套循环读取矩阵元素
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.printf("请输入元素 [%d][%d]: ", i, j);
array[i][j] = sc.nextInt();
}
}
System.out.println("\n原始矩阵:");
displayMatrix(array); // 显示原始矩阵
System.out.println("\n矩阵顺时针旋转90度后:");
int[][] rotatedArray = rotateMatrixClockwise(array); // 旋转矩阵
displayMatrix(rotatedArray); // 显示旋转后的矩阵
sc.close();
}
/**
* 显示矩阵内容
* @param matrix 要显示的矩阵
*/
public static void displayMatrix(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.printf("%4d", matrix[i][j]); // 格式化输出,使对齐
}
System.out.println(); // 每行结束后换行
}
}
// 旋转矩阵的方法将在下一节详细介绍
public static int[][] rotateMatrixClockwise(int[][] matrix) {
// 占位符,将在下一节实现
return new int[0][0];
}
}在上述代码中,我们首先使用 Scanner 类获取用户输入的行数 m 和列数 n。然后,根据这些尺寸声明并初始化二维数组 array。接着,通过两个嵌套的 for 循环,逐个提示用户输入每个矩阵元素,并将其存储到对应的位置。请注意,为了良好的用户体验,我们增加了提示信息,并使用 printf 格式化输出,使矩阵显示更整齐。
2. 2D 数组的显示
为了验证输入是否正确以及查看旋转后的结果,我们需要一个通用的方法来显示二维数组的内容。displayMatrix 方法就是为此目的设计的。它接收一个二维数组作为参数,并以矩阵的形式打印出来。
/**
* 显示矩阵内容
* @param matrix 要显示的矩阵
*/
public static void displayMatrix(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) { // 遍历行
for (int j = 0; j < matrix[i].length; j++) { // 遍历列
System.out.printf("%4d", matrix[i][j]); // 使用 %4d 保证每个数字占用4个字符宽度,方便对齐
}
System.out.println(); // 每行打印完毕后换行
}
}此方法遍历矩阵的每一行和每一列,并打印出元素。matrix.length 获取行数,matrix[i].length 获取第 i 行的列数。这种方式确保了即使是锯齿数组(不规则的二维数组)也能正确显示。
立即学习“Java免费学习笔记(深入)”;
3. 2D 数组的90度顺时针旋转
矩阵的90度顺时针旋转是一个常见的操作。其基本思想是将原始矩阵的行变为新矩阵的列,并且顺序需要反转。对于一个 m x n 的矩阵 A,旋转90度后会变成一个 n x m 的矩阵 B。原始矩阵 A[i][j] 的元素会移动到新矩阵 B[j][(m-1)-i] 的位置。
在实现旋转功能时,一个常见的陷阱是尝试在原数组上进行就地旋转,这对于非方形矩阵来说非常复杂且容易出错。更通用和推荐的方法是创建一个新的辅助数组来存储旋转后的结果。
/**
* 将矩阵顺时针旋转90度
* @param matrix 原始矩阵
* @return 旋转90度后的新矩阵
*/
public static int[][] rotateMatrixClockwise(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return new int[0][0]; // 处理空矩阵或无效矩阵
}
int originalRows = matrix.length; // 原始矩阵的行数
int originalCols = matrix[0].length; // 原始矩阵的列数
// 旋转90度后,新矩阵的行数是原始矩阵的列数,新矩阵的列数是原始矩阵的行数
int[][] rotatedMatrix = new int[originalCols][originalRows];
// 遍历原始矩阵,将元素放置到旋转后的矩阵的正确位置
// 原始矩阵的 (i, j) 元素,在新矩阵中位于 (j, originalRows - 1 - i)
for (int i = 0; i < originalRows; i++) {
for (int j = 0; j < originalCols; j++) {
rotatedMatrix[j][originalRows - 1 - i] = matrix[i][j];
}
}
return rotatedMatrix;
}实现思路详解:
- 确定新矩阵尺寸: 如果原始矩阵是 m x n,则旋转90度后,新矩阵将是 n x m。因此,我们创建 new int[originalCols][originalRows] 的新矩阵。
-
映射关系: 原始矩阵 matrix[i][j] 中的元素,在旋转后的矩阵 rotatedMatrix 中的位置是 rotatedMatrix[j][originalRows - 1 - i]。
- j 作为新矩阵的行索引:这是因为原始矩阵的列变成了新矩阵的行。
- originalRows - 1 - i 作为新矩阵的列索引:这是因为原始矩阵的行变成了新矩阵的列,并且需要进行反转(从下往上)以实现顺时针旋转。originalRows - 1 是原始矩阵的最后一行索引。
这种方法避免了在原始代码中出现的硬编码尺寸(如 M=4)和错误的循环边界(如 M-4),同时也能正确处理非方形矩阵。
4. 完整示例代码
将以上所有部分整合到一个 MatrixOperations 类中,即可得到一个完整的、可运行的程序。
import java.util.Scanner;
public class MatrixOperations {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入矩阵的行数 (m): ");
int m = sc.nextInt();
System.out.print("请输入矩阵的列数 (n): ");
int n = sc.nextInt();
int[][] array = new int[m][n];
System.out.println("请输入矩阵的元素:");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.printf("请输入元素 [%d][%d]: ", i, j);
array[i][j] = sc.nextInt();
}
}
System.out.println("\n--- 原始矩阵 ---");
displayMatrix(array);
System.out.println("\n--- 矩阵顺时针旋转90度后 ---");
int[][] rotatedArray = rotateMatrixClockwise(array);
displayMatrix(rotatedArray);
sc.close();
}
/**
* 显示矩阵内容
* @param matrix 要显示的矩阵
*/
public static void displayMatrix(int[][] matrix) {
if (matrix == null || matrix.length == 0 || (matrix.length > 0 && matrix[0].length == 0)) {
System.out.println("[空矩阵]");
return;
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.printf("%4d", matrix[i][j]);
}
System.out.println();
}
}
/**
* 将矩阵顺时针旋转90度
* @param matrix 原始矩阵
* @return 旋转90度后的新矩阵
*/
public static int[][] rotateMatrixClockwise(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return new int[0][0]; // 处理空矩阵或无效矩阵
}
int originalRows = matrix.length;
int originalCols = matrix[0].length;
int[][] rotatedMatrix = new int[originalCols][originalRows];
for (int i = 0; i < originalRows; i++) {
for (int j = 0; j < originalCols; j++) {
rotatedMatrix[j][originalRows - 1 - i] = matrix[i][j];
}
}
return rotatedMatrix;
}
}注意事项与总结
- 避免硬编码尺寸: 在处理二维数组时,应始终使用 matrix.length 获取行数,使用 matrix[i].length 获取列数,而不是使用固定的常量,以确保代码的通用性。
- 清晰的逻辑分离: 将输入、显示和旋转等功能封装在独立的函数中,可以提高代码的可读性和可维护性。
- 处理非方形矩阵: 90度顺时针旋转对于 m x n 的矩阵会产生一个 n x m 的矩阵。使用辅助数组并根据正确的映射关系 rotatedMatrix[j][originalRows - 1 - i] = matrix[i][j] 是最健壮的实现方式。
- 输入循环与显示/操作循环: 确保输入循环完全结束后再进行显示或旋转操作。原始问题中将旋转操作放在显示循环内部是错误的,会导致多次旋转和不正确的输出。
- 内存考虑: 使用辅助数组会增加内存开销,其大小与原始矩阵相同。对于非常大的矩阵,可能需要考虑更复杂的就地旋转算法(通常只适用于方形矩阵)。
通过遵循本教程的指导,您可以有效地在Java中处理二维数组的输入、显示和90度顺时针旋转,并能够应对各种矩阵尺寸的挑战。










