Java 稀疏数组实现(二维数组 ↔ 稀疏数组 互转)
原理说明
- 稀疏数组适用场景:二维数组中大量元素为默认值(0),只有少量有效数据,用稀疏数组压缩节省空间。
- 稀疏数组结构
- 第一行:
[总行数, 总列数, 有效元素个数] - 后续每一行:
[行下标, 列下标, 对应数值]
- 第一行:
- 转换流程
- 二维数组 → 稀疏数组:遍历统计有效数据,构建稀疏数组
- 稀疏数组 → 二维数组:读取首行列信息,新建空二维数组,回填有效值
完整代码
public class SparseArray { public static void main(String[] args) { // 1. 创建原始二维数组(模拟棋盘,0为空,1=黑子,2=白子) int[][] chessArr = new int[11][11]; chessArr[1][2] = 1; chessArr[2][3] = 2; chessArr[4][5] = 1; System.out.println("===== 原始二维数组 ====="); printTwoDArray(chessArr); // 2. 二维数组转稀疏数组 int[][] sparseArr = twoDToSparse(chessArr); System.out.println("\n===== 转换后的稀疏数组 ====="); printTwoDArray(sparseArr); // 3. 稀疏数组还原为二维数组 int[][] recoverArr = sparseToTwoD(sparseArr); System.out.println("\n===== 稀疏数组还原后的二维数组 ====="); printTwoDArray(recoverArr); } /** * 二维数组转稀疏数组 * @param twoDArr 原始二维数组 * @return 稀疏数组 */ public static int[][] twoDToSparse(int[][] twoDArr) { // 1. 统计有效数字总数(非0) int validCount = 0; int rowLen = twoDArr.length; int colLen = twoDArr[0].length; for (int i = 0; i < rowLen; i++) { for (int j = 0; j < colLen; j++) { if (twoDArr[i][j] != 0) { validCount++; } } } // 2. 创建稀疏数组:行数=有效数+1,固定3列(行、列、值) int[][] sparseArr = new int[validCount + 1][3]; // 第一行保存原数组信息:总行、总列、有效个数 sparseArr[0][0] = rowLen; sparseArr[0][1] = colLen; sparseArr[0][2] = validCount; // 3. 填充有效数据到稀疏数组 int index = 1; // 稀疏数组从第1行开始存数据 for (int i = 0; i < rowLen; i++) { for (int j = 0; j < colLen; j++) { if (twoDArr[i][j] != 0) { sparseArr[index][0] = i; sparseArr[index][1] = j; sparseArr[index][2] = twoDArr[i][j]; index++; } } } return sparseArr; } /** * 稀疏数组还原二维数组 * @param sparseArr 稀疏数组 * @return 还原后的原始二维数组 */ public static int[][] sparseToTwoD(int[][] sparseArr) { // 1. 读取稀疏数组第一行,获取原数组行列 int rowTotal = sparseArr[0][0]; int colTotal = sparseArr[0][1]; int[][] twoDArr = new int[rowTotal][colTotal]; // 2. 遍历稀疏数组剩余行,回填数值 for (int i = 1; i < sparseArr.length; i++) { int row = sparseArr[i][0]; int col = sparseArr[i][1]; int val = sparseArr[i][2]; twoDArr[row][col] = val; } return twoDArr; } /** * 工具方法:打印二维数组 */ public static void printTwoDArray(int[][] arr) { for (int[] row : arr) { for (int data : row) { System.out.printf("%d\t", data); } System.out.println(); } } }运行输出结果
===== 原始二维数组 ===== 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ===== 转换后的稀疏数组 ===== 11 11 3 1 2 1 2 3 2 4 5 1 ===== 稀疏数组还原后的二维数组 ===== 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0核心方法拆解
twoDToSparse- 两次循环:第一次统计非 0 元素数量,创建稀疏数组;第二次遍历赋值坐标与数值
sparseToTwoD- 先用稀疏数组首行创建全 0 二维数组,再逐行读取坐标回填数据
- 工具方法
printTwoDArray:统一打印逻辑,复用代码
拓展:持久化读写稀疏数组(存入文件 / 读取文件)
如果需要把稀疏数组保存到本地文件、下次读取恢复棋盘,可追加以下读写方法:
import java.io.*; // 稀疏数组写入文件 public static void writeSparseToFile(int[][] sparseArr, String path) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter(path)); for (int[] row : sparseArr) { bw.write(row[0] + "," + row[1] + "," + row[2]); bw.newLine(); } bw.close(); } // 文件读取还原稀疏数组 public static int[][] readSparseFromFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); String line; java.util.List<int[]> list = new java.util.ArrayList<>(); while ((line = br.readLine()) != null) { String[] split = line.split(","); int row = Integer.parseInt(split[0]); int col = Integer.parseInt(split[1]); int val = Integer.parseInt(split[2]); list.add(new int[]{row, col, val}); } br.close(); // list转二维数组 int[][] sparse = new int[list.size()][3]; for (int i = 0; i < list.size(); i++) { sparse[i] = list.get(i); } return sparse; }调用示例:
writeSparseToFile(sparseArr, "chess.txt"); int[][] fileSparse = readSparseFromFile("chess.txt");