当前位置: 首页 > news >正文

Java 稀疏数组实现(二维数组 ↔ 稀疏数组 互转)

原理说明

  1. 稀疏数组适用场景:二维数组中大量元素为默认值(0),只有少量有效数据,用稀疏数组压缩节省空间。
  2. 稀疏数组结构
    • 第一行:[总行数, 总列数, 有效元素个数]
    • 后续每一行:[行下标, 列下标, 对应数值]
  3. 转换流程
    • 二维数组 → 稀疏数组:遍历统计有效数据,构建稀疏数组
    • 稀疏数组 → 二维数组:读取首行列信息,新建空二维数组,回填有效值

完整代码

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

核心方法拆解

  1. twoDToSparse
    • 两次循环:第一次统计非 0 元素数量,创建稀疏数组;第二次遍历赋值坐标与数值
  2. sparseToTwoD
    • 先用稀疏数组首行创建全 0 二维数组,再逐行读取坐标回填数据
  3. 工具方法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");
http://www.jsqmd.com/news/1233064/

相关文章:

  • 2026年物流公司推荐榜:高效智慧物流/冷链专线/整车零担/跨境货运头部企业实力优选 - 甄选服务推荐
  • 深度学习GPU推理优化:调度策略与性能调优实战
  • 微电网优化运行:可再生能源与储能的不确定性挑战
  • 深入解析CPSW中断与DMA寄存器:嵌入式网络驱动性能优化实战
  • 基于Java的“番茄TV”视频点播系统的设计
  • ARM AINTC中断控制器:嵌入式实时系统的核心机制与实战配置
  • 图片转视频工具:原理、实现与优化指南
  • AI赋能:提升效率与落地的关键路径
  • C++多线程高性能金融系统架构:从零构建微秒级行情处理引擎
  • Linux进程与线程的核心区别及多线程编程实践
  • STC单片机驱动16X16 LED点阵的硬件设计与软件实现
  • 2026 年新发布:文县专业的高铁施工巡检车供应商哪家好,揭秘:这辆车如何让高铁安全率飙升10% - 实业推荐官【官方】
  • Spring EL表达式:动态配置与业务逻辑的终极解决方案
  • Pinia 实战:模块化架构设计、统一调度与持久化方案全解
  • 504网关超时错误解析与解决方案
  • 2026年跨行业转行面试没经验?AI三步挖掘可迁移能力,让面试官觉得「你是对的人」
  • Ubuntu 20.04搭建vsftpd服务器完整指南
  • 瑞德克斯平台:产品理解成本的标准分析
  • IE终结与现代浏览器技术演进及迁移策略
  • AI技术革命催生的22个新兴职业与能力矩阵
  • MLCC技术解析:从基础原理到AI与车规应用
  • U盘系统盘制作与恢复全指南
  • C++网店购物管理系统实战:面向对象设计、STL应用与数据持久化
  • 2026 年 7 月新发布:润州专业的防火纤维生产商哪家可靠,揭秘:它如何拯救你的家庭火灾风险 - 企业信息推荐【官方】
  • StarRocks 3.1.1 深度优化:GROUP BY 非聚合字段查询提速落地方案
  • C++与Vue.js高效整合开发:架构设计与Electron实战
  • AI编程工具选型指南:Copilot、Cursor与Cline的隐性成本对比
  • 乌鲁木齐公司注册:亲测有效的方法与案例分享
  • C++入门指南:从环境搭建到核心概念与项目实践
  • 吃透 Android 底层触控逻辑,根治项目常见交互 Bug