Java数据结构:稀疏数组(Sparse Array)的创建和文件存取

稀疏数组Sparse Array

一、实际需求

五子棋是一种双人对弈的策略性棋类游戏,在我们用Java编写五子棋程序时,我们会设法实现存盘退出续上盘这样的一些功能。存盘退出,实际上就是要求我们对当前的棋盘进行记录并且写入到文件里面,这样选择续上盘的功能时才能从文件当中读档,恢复到上次保存的棋局当中。

我们在存储如左图所示的棋盘时,通常会选择一个二维数组,如右图所示。但是在大多数情况下该二维数组的很多值是默认值0,这样在无形当中就记录了很多没有意义的数据。这时可以采用稀疏数组,减少数据的存储量,设法不去存储默认值。

二、基本介绍

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方法是:

  1. 记录二维数组一共有几行几列,有多少个不同位置的元素;
  2. 把不同的元素的行列及值记录在一个小规模的数组(即稀疏数组)中,从而缩小程序的规模。

下面简单地举例说明:

左图是一个二维数组的矩阵表示,右图是将二维数组转换成的稀疏数组。

三、应用实例

  1. 使用稀疏数组,来保留类似前面的二维数组棋盘、地图等等
  2. 疏数组存盘,并且可以重新恢复原来的维数组
  3. 体思路分析

     4. 代码实现

四、课后练习

要求

  1. 在前面的基础上,将稀疏数组保存到磁盘上,比如map.data
  2. 恢复原来的数组时,读取map.data进行恢复

代码

package linerStructures;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class sparseArray {
    public static void main(String args[]){
        int chessArray1[][]=new int [11][11];  //创建一个二维数组表示初始棋盘
        chessArray1[1][2]=1;  //用 1 表示棋盘上的黑子
        chessArray1[2][3]=2;  //用 2 表示棋盘上的蓝子
        //输出棋盘
//        for(int[] row:chessArray1){
//            for(int data:row){
//                System.out.printf("%d\t",data);
//            }
//            System.out.println();
//        }

        //将二维数组 转 稀疏数组
        //1、 先遍历 二维数组,得到非 0 数据的个数,用于创建 稀疏数组
        //   二维数组 转 稀疏数组的思路
        //   1) 遍历原始的二维数组,得到有效数据的个数 sum
        //   2) 根据sum 就可以创建 稀疏数组 sparseArr   int[sum + 1] [3]
        //   3) 将二维数组的有效数据数据存入到 稀疏数组

        int num=0; //记录数据的个数
        for(int i=0;i<chessArray1.length;i++){
            for(int j=0;j<chessArray1[0].length;j++){
                if(chessArray1[i][j]!=0){
                    num++;
                }
            }
        }

        //2、 接着创建一个 稀疏数组
        int sparseArray1[][]=new int [num+1][3]; //建立一个num+1行,2列的 稀疏数组
        sparseArray1[0][0]=11;//第一行记录 二维数组 的行列以及数据的个数
        sparseArray1[0][1]=11;
        sparseArray1[0][2]=num;

        //3、 取得非 0 位置的值
        int count=0;
        for(int i=0;i<chessArray1.length;i++){
            for(int j=0;j<chessArray1[0].length;j++){
                if(chessArray1[i][j]!=0){
                    sparseArray1[count+1][0]=i;
                    sparseArray1[count+1][1]=j;
                    sparseArray1[count+1][2]=chessArray1[i][j];
                    count++;
                }
            }
        }

        //4、 输出 稀疏数组
//        for(int i=0;i<sparseArray1.length;i++){
//            System.out.printf("%d\t%d\t%d\n",sparseArray1[i][0],sparseArray1[i][1],sparseArray1[i][2]);
//        }

        //5、 将 稀疏数组 恢复成 二维数组
        //    稀疏数组转原始的二维数组的思路
        //    1) 先读取稀疏数组的第一行,根据第一行的数据,
        //       创建原始的二维数组,比如上面的  chessArr2 = int [11][11]
        //    2) 在读取稀疏数组后几行的数据,并赋给 原始的二维数组 即可.
        int row=sparseArray1[0][0],col=sparseArray1[0][1];
        int chessArray2[][]=new int[row][col];  //重新创建一个二维数组
        for(int i=1;i<sparseArray1.length;i++){
            //稀疏数组每一行的第一列是二维数组里的行号,第二列是列号,第三列是数据
            chessArray2[sparseArray1[i][0]][sparseArray1[i][1]]=sparseArray1[i][2];
        }
//        for(int[] r:chessArray2){
//            for(int data:r){
//                System.out.printf("%d\t",data);
//            }
//            System.out.println();
//        }

        //6、 练习题 :将稀疏数组输出到文件当中 然后再从文件中读取并恢复二维数组
        try{
            String string=new String("sparseArray.txt");
            FileWriter fw=new FileWriter(string);
            for(int[] row1:sparseArray1) {
                for (int data : row1) {
                    fw.write(data+"\t");
                }
            }
            fw.close();
        }catch(IOException e){
            e.printStackTrace();
        }

        try {
            List<Integer> l=new ArrayList<>();
            String string=new String("sparseArray.txt");
            File f=new File(string);
            BufferedReader br=new BufferedReader(new FileReader(f));
//            String s=br.readLine();
//            System.out.println(s);
//            String[] numbers=s.split("\t");
//            System.out.println(numbers[3]);  //用来检查错误的代码
            String s=null;
            while((s=br.readLine())!=null){
                String[] sn=s.split("\t");
                for(String sc:sn) {
                        int i = Integer.parseInt(sc);
                        l.add(i);
                    }
            }
            int r=l.get(0),c=l.get(1);
            int chessArray3[][]=new int[r][c];  //重新创建一个二维数组
            for(int i=3;i<l.size();i++){
                //稀疏数组每一行的第一列是二维数组里的行号,第二列是列号,第三列是数据
                if(i%3==0) chessArray3[l.get(i)][l.get(i+1)]=l.get(i+2);
            }
            for(int[] three:chessArray3) {
                for (int data : three) {
                    System.out.printf("%d\t", data);
                }
                System.out.println();
            }
            br.close();
        }catch (IOException e){
            e.printStackTrace();
        }
   }
}

笔记

split()函数报错:读取文件的时候,分割从文件当中读到的一整行数据,忘记写文件的时候用的分隔符是‘\t’。所以一直在用空格去分割,自然得不到正确的结果。

参考资料

[1] 尚硅谷-韩顺平 Java数据结构和算法课件

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值