稀疏数组&五子棋存储

325 阅读3分钟

线性结构与非线性结构

线性结构

  1. 数据元素之间存在一对一的线性关系

  2. 线性结构有两种不同的存储结构,即顺序存储结构(数组)和链式存储结构(链表)。顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的

  3. 链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息

  4. 线性结构常见的有:数组、队列、链表和栈

非线性结构

非线性结构包括:二维数组,多维数组,广义表,树结构,图结构

稀疏数组和队列

稀疏数组

场景

image.png

如果该五子棋盘提供有保存功能,该棋盘如果转换为二维数组,很多默认值为0,因此记录了很多没有意义的数据,此时考虑使用稀疏数组进行存储。

分析:

image.png 数据从上到下,从左到右依次表示:

  • 第一行:数组中有11行11列2个有效的值
  • 第二行:数组第一行第二列的值有效值为1
  • 第三行:数组第二行第三列的有效值为2

概念

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

稀疏数组的处理方法是:

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

代码实现

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 稀疏数组
 *
 * @author zhangshuai
 */
public class SpareArray {

    public static void main(String[] args) throws IOException {
        int[][] chessArray = createArray();
        int sum = initSum(chessArray);
        int[][] spareArray = createSpareArray(sum, chessArray);
        System.out.println("--------------棋盘");
        printArray(chessArray);
        System.out.println("--------------稀疏数组");
        printArray(spareArray);
        System.out.println("--------------将稀疏数组写入磁盘...");
        writerData(spareArray);
        System.out.println("--------------读取磁盘中的数据...");
        int[][] resultSpareArray = readData();
        System.out.println("--------------文件中读出的稀疏数组...");
        printArray(resultSpareArray);
        System.out.println("--------------稀疏矩阵转换为原始棋盘...");
        int[][] result = initArray(resultSpareArray);
        printArray(result);
    }

    /**
     * 稀疏矩阵转换为原始矩阵
     *
     * @param resultSpareArray
     * @return
     */
    private static int[][] initArray(int[][] resultSpareArray) {
        int[][] result = new int[resultSpareArray[0][0]][resultSpareArray[0][1]];
        // 原始棋盘中的数字个数
        int sum2 = resultSpareArray[0][2];
        for (int i = 1; i <= sum2; i++) {
            result[resultSpareArray[i][0]][resultSpareArray[i][1]] = resultSpareArray[i][2];
        }
        return result;
    }

    /**
     * 读取磁盘中的数据
     *
     * @return
     * @throws IOException
     */
    private static int[][] readData() throws IOException {
        File file = new File("E:" + File.separator + "study" + File.separator + "map.data");
        FileInputStream fis = null;
        InputStreamReader reader = null;
        int[][] resultSpareArray = null;
        try {
            System.out.println("打开文件中...");
            // 打开本地磁盘中的文件
//            Desktop.getDesktop().open(file);
            fis = new FileInputStream(file);
            reader = new InputStreamReader(fis, StandardCharsets.UTF_8);
            StringBuffer sb = new StringBuffer();
            while (reader.ready()) {
                sb.append((char) reader.read());
            }
            System.out.println("文件中的内容...");
            System.out.println(sb);
            String str = sb.toString();
            String[] strReg = str.split(",");
            // 11 11 2 1 2 1 2 3 2
            resultSpareArray = new int[strReg.length / 3][3];
            int index = 0;
            for (String str2 : strReg) {
                resultSpareArray[(index - (index % 3)) / 3][index % 3] = Integer.parseInt(str2);
                index++;
            }
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (fis != null) {
                fis.close();
            }
        }
        return resultSpareArray;
    }

    /**
     * 将稀疏数组写入磁盘
     *
     * @param spareArray
     * @throws IOException
     */
    private static void writerData(int[][] spareArray) throws IOException {
        File file = new File("E:" + File.separator + "study" + File.separator + "map.data");
        try (FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter write = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
            for (int[] ints : spareArray) {
                write.append(String.valueOf(ints[0])).append(",").append(String.valueOf(ints[1])).append(",").append(String.valueOf(ints[2])).append(",");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("写入文件成功!");
        }
    }

    /**
     * 打印二维数组
     *
     * @param array
     */
    private static void printArray(int[][] array) {
        for (int[] arr : array) {
            for (int a : arr) {
                System.out.print(a + " ");
            }
            System.out.println();
        }

    }

    /**
     * 初始化稀疏数组
     *
     * @param sum
     * @param chessArray 棋盘
     * @return
     */
    private static int[][] createSpareArray(int sum, int[][] chessArray) {
        int[][] spareArray = new int[sum + 1][3];
        // 稀疏数组的row
        int row = chessArray.length;
        // 稀疏数组的col
        int col = chessArray[0].length;
        spareArray[0][0] = row;
        spareArray[0][1] = col;
        spareArray[0][2] = sum;
        // 记录稀疏数组的行数
        int k = 1;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (sum < k) {
                    break;
                }
                if (chessArray[i][j] != 0) {
                    spareArray[k][0] = i;
                    spareArray[k][1] = j;
                    spareArray[k][2] = chessArray[i][j];
                    k++;
                }
            }
        }

        return spareArray;
    }

    /**
     * 遍历棋盘
     *
     * @param chessArray 棋盘
     * @return 棋盘中共有多少个数
     */
    private static int initSum(int[][] chessArray) {
        int sum = 0;
        for (int[] arr : chessArray) {
            for (int a : arr) {
                if (a != 0) {
                    sum++;
                }
            }
        }

        return sum;
    }

    /**
     * 创建棋盘
     *
     * @return 返回的棋盘的二维数组
     */
    private static int[][] createArray() {
        int[][] chessArray = new int[11][11];
        chessArray[1][2] = 1;
        chessArray[2][3] = 2;
        return chessArray;
    }

}