Java实现二维数组和稀疏数组的转换

稀疏数组

简介:当编写的二维数组中存在很多不用的点但初始化时都赋值为0时,这个二维数组的观赏性很低并且非常浪费存储空间,这个时候会选择使用稀疏数组对这个二维数组进行简化压缩。

稀疏数组是当一个二维数组大部分数据为0其他相同数据时,对这个数组的一种简化的保存形式。
处理规则
①记录二维数组有几行几列,并把不同值的元素保存下来。
②记录不同值元素的坐标,并把它保存在一个小数组中,从而缩小程序规模。

用一个简单模型进行直观分析:
下图是一个11×11二维数组,其中有两个非0元素(上述①的不同值的元素
在这里插入图片描述
转化为稀疏数组:
在这里插入图片描述

  • 第一行记录数组的总行列数以及有值元素的个数;
  • 之后的每行都会记录各个非零元素的“坐标”以及数值);
  • 稀疏数组固定为“行”、“列”、“值”3列,行数由不同值的元素个数决定。

二维数组——>稀疏数组

  1. 遍历二维数组,记录不同值的元素的个数sum;
  2. 根据有效数据的个数创建新的数组,作为稀疏数组
//行数为“不同值的元素个数+1”:
//因为第一行是记录“二维数组的行列数”和“不同值的元素个数”
 int[ ][ ] sparseArr=new int [sum+1][3];
//列数固定为3
  1. 将原始二维数组中的有效数据存入新建数组中。

    在实际应用当中,填充完毕的稀疏数组需要存盘到一个文件中,也就是把计算机中的信息存储到磁盘上,多用于游戏存档读档(比如说围棋游戏就很适合),并且可以恢复成原始的二维数组

操作流程:

  • 第一步:创建并输出原始二维数组
public class SparseArray {
    public static void main(String[] args) {
        //创建一个大小为11*11的二维数组
        int chessArr1[][] = new int[11][11];
        //定义两个不同值数据
        chessArr1[2][2] = 3;
        chessArr1[6][4] = 8;
        //遍历输出二维数组
        //遍历棋盘二维数组中的每一行
        for (int row[] : chessArr1) {
            //遍历每一行的每一个元素
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            //每输出一行就换行
            System.out.println();
        }
    }
}

运行结果图:
在这里插入图片描述

  • 第二步:计算有效数据的个数
//将二维数组转换压缩成稀疏数组的思路
        //1.首先遍历二维数组并计算有效数据的个数
        int sum = 0;//计算有效数据的个数
        for (int row[] : chessArr1) {
            //遍历每一行的每一个元素
            for (int data : row) {
                if (data != 0)
                    sum++;
            }
        }
        System.out.println(sum);

运行结果图:
在这里插入图片描述

  • 第三步:填充稀疏数组并将其打印出来
int[][] sparseArr = new int[12][3];//行数为sum+1,列数固定为3
        //初始化稀疏数组第一行
        sparseArr[0][0] = 11;
        sparseArr[0][1] = 11;
        sparseArr[0][2] = sum;
        // 遍历二维数组,将非零的值存入sparseArr(稀疏数组)中
        int count = 0;// count用于记录是第几个有效元素
        for (int i = 0; i < 11; i++) {// 遍历每一行
            for (int j = 0; j < 11; j++) {// 遍历每一列
                if (chessArr1[i][j] != 0) {// 如果发现有效数据
                    // sparseArr[?][0]=i;//第一列的值就是该有效元素的行数
                    // sparseArr[?][1]=j;//第二列的值就是该有效元素的列数
                    // sparseArr[?][2]=chessArr1[i][j];//第三列的值就是该有效元素其本身
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArr1[i][j];
                }
            }
        }
        System.out.println();
        System.out.println("压缩成稀疏数组表现为:");
        // 遍历打印稀疏数组
        for (int i = 0; i < sum + 1; i++) {
            //格式化输出每一行的三列数,并且每打印三个数换行
            System.out.printf("%d\t %d\t %d\t", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
            System.out.println();
        }

运行结果图:
在这里插入图片描述

稀疏数组——>二维数组

  1. 先读取稀疏数组第一行,得到二维数组的行列数,创建一个新的二维数组(请看上面的二维数组⬆)
 int [ ][ ]=new int [11][11];
  1. 再读取剩下几行的数据即可

    在实际应用当中,先将文件恢复成稀疏数组,再转换成原始二维数组

操作流程:

  • 第一步:读取稀疏数组的值恢复原始的二维数组

  • 第二步:读取稀疏数组后几行数据,将有效值填充到二维数组的指定位置

// 将稀疏数组转换为二维数组的思路
        // 1.读取稀疏数组第一行的值,根据第一行的值来创建原始的二维数组
        int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
        // 2.读取后几行的数据填充二维数组
        for (int i = 1; i < sparseArr.length; i++) {// 因为是从第二行开始读数的,所以要从i=1开始
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        // 输出原始的二维数组
        System.out.println();
        System.out.println("打印恢复后的二维数组");
        for (int[] row : chessArr2) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }

运行结果图:
在这里插入图片描述

在上面的基础上,将稀疏数组保存到磁盘“map.data”上,恢复原来的数组时,读取“map.data”进行恢复。

完整code

import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class SparseArray {

    public static void main(String[] args) throws Exception {// 在方法声明部分使用,表示该方法可能产生此异常,如果在方法声明处使用了throws
        // 声明异常,则该方法产生异常也不必捕获,会直接把异常抛出到调用该方法的地方。
        // 创建一个原始的二维数组11*11
        int chessArr1[][] = new int[11][11];
        chessArr1[2][2] = 3;
        chessArr1[6][4] = 8;
        // 输出原始的二维数组
        System.out.println("原始二维数组:");
        for (int[] row : chessArr1) { // 遍历棋盘二维数组中的每一个一维数组
            for (int data : row) { // 遍历一维数组中的每一个元素
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }
        // 将二维数组转换为稀疏数组的思路
        // 1.首先遍历二维数组并计算有效数据的个数
        int sum = 0;// 计算有效数据的个数
        for (int i = 0; i < chessArr1.length; i++) {
            for (int j = 0; j < chessArr1.length; j++) {
                if (chessArr1[i][j] != 0) {
                    sum++;
                }
            }
        }
        // 2.创建对应的稀疏数组 (int[ ][ ] sparseArr=new int [sum+1][3];)
        int[][] sparseArr = new int[sum + 1][3];
        sparseArr[0][0] = 11;
        sparseArr[0][1] = 11;
        sparseArr[0][2] = sum;
        // 遍历二维数组,将非零的值存入sparseArr(稀疏数组)中
        int count = 0;// count用于记录是第几个有效元素
        for (int i = 0; i < chessArr1.length; i++) {// 遍历每一行
            for (int j = 0; j < chessArr1.length; j++) {// 遍历每一列
                if (chessArr1[i][j] != 0) {// 如果发现有效数据
                    // sparseArr[?][0]=i;//第一列的值就是该有效元素的行数
                    // sparseArr[?][1]=j;//第二列的值就是该有效元素的列数
                    // sparseArr[?][2]=chessArr1[i][j];//第三列的值就是该有效元素其本身
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArr1[i][j];
                }
            }
        }
        // 保存稀疏数组
        File file = new File("C:\\Users\\18147\\Desktop\\map.data");//这里写你创建文件的地址,我是直接在桌面上创建了一个
        FileOutputStream fos = new FileOutputStream(file);

        OutputStreamWriter write = new OutputStreamWriter(fos, "UTF-8");
        // 输出稀疏数组的形式
        System.out.println();
        System.out.println("得到的稀疏数组为~~~");
        for (int i = 0; i < sparseArr.length; i++) {
            System.out.printf("%d\t%d\t%d\t\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);

            if (i == sparseArr.length - 1) {
                write.append(sparseArr[i][0] + "," + sparseArr[i][1] + "," + sparseArr[i][2]);
            } else {
                write.append(sparseArr[i][0] + "," + sparseArr[i][1] + "," + sparseArr[i][2] + ",");
            }
        }

        System.out.println("写入文件中...");
        write.close();
        fos.close();

        System.out.println("打开文件中...");
        Desktop.getDesktop().open(file);

        System.out.println("------------------------------先读取_map.data");
        // 创建 FileReader 对象
        FileInputStream fis = new FileInputStream(file);

        InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
        StringBuffer sb = new StringBuffer();
        while (reader.ready()) {
            sb.append((char) reader.read());// 转成char加到StringBuffer对象中
        }

        System.out.println(sb.toString());
        reader.close();// 关闭读取流
        fis.close();// 关闭输入流,释放系统资源

        System.out.println("------------------------------恢复成稀疏数组_sparseArrHf");
        System.out.println();
        System.out.println("压缩成稀疏数组表现为:");
        // 遍历打印稀疏数组
        for (int i = 0; i < sparseArr.length; i++) {
            // 格式化输出每一行的三列数,并且每打印三个数换行
            System.out.printf("%d\t %d\t %d\t", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
            System.out.println();
        }

        // 将稀疏数组转换为二维数组的思路
        // 1.读取稀疏数组第一行的值,根据第一行的值来创建原始的二维数组
        int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
        // 2.读取后几行的数据填充二维数组
        for (int i = 1; i < sparseArr.length; i++) {// 因为是从第二行开始读数的,所以要从i=1开始
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        // 输出原始的二维数组
        System.out.println();
        System.out.println("打印恢复后的二维数组");
        for (int[] row : chessArr2) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }
    }
}

运行结果图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值