• 数据结构与算法(一): 稀疏数组


    问题引入

    在五子棋游戏或类似的游戏中,我们可以把整个棋盘想象成是一个有规律的二维数组,其值由0、1、2三个数字组成,0代表空白区域,1代表白子,2代表黑子。这种情况:即当一个数组中大部分元素为0或者为同一值时,存储该数组数据可以使用稀疏数组来对原始数组进行精简,以减少原始数组中无用数据所占的空间。

    普通二维数组与稀疏数组

    下图表示的是一个12×12大小的二维数组与之对应的稀疏数组表示,其中普通二维数组中有11个有效值,其余的全为无用数据0填充。稀疏数组的第一行表示有一个12行12列且11个有效数值的二维数组。第二行表示,二维数组中的第2行(从0开始)、第4列的数值为1。从第二行开始,每一行表示的都是二维数组中数值的行列位置和真实值。

    在这里插入图片描述 在这里插入图片描述

    代码实现

    生成二维数组

    private int[][] generatorArray() {
    	// 初始化二维数组
        int[][] arr = new int[12][12];
        // 二维数组赋值
        arr[2][4] = 1;
        arr[2][5] = 1;
        arr[3][4] = 1;
        arr[3][5] = 1;
        arr[3][6] = 2;
        arr[3][7] = 2;
        arr[4][5] = 2;
        arr[4][6] = 1;
        arr[5][5] = 1;
        arr[5][6] = 2;
        arr[5][7] = 2;
        System.out.println("原始二维数组为:");
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + "\t");
            }
            System.out.println();
        }
        System.out.println();
        return arr;
    }
    

    运行结果

    原始二维数组为:
    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	1	0	0	0	0	0	0	
    0	0	0	0	1	1	2	2	0	0	0	0	
    0	0	0	0	0	2	1	0	0	0	0	0	
    0	0	0	0	0	1	2	2	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	0	0	0	0	0	
    

    二维数组转换成稀疏数组

    private int[][] toSparseArray(int[][] originalArray) {
    	// 获得原始数组行列、有效值初始化稀疏数组
    	int sum = 0;
    	for (int i = 0; i < originalArray.length; i++) {
    	    for (int j = 0; j < originalArray[i].length; j++) {
    	        if (originalArray[i][j] != 0) {
    	            sum += 1;
    	        }
    	    }
    	}
    	// 稀疏数组length为有效值个数+1
    	int[][] sparseArray = new int[sum+1][3];
    	// 行
    	sparseArray[0][0] = originalArray.length;
    	// 列
    	sparseArray[0][1] = originalArray[0].length;
    	// 有效值个数
    	sparseArray[0][2] = sum;
    	// 赋值
    	int count = 0;
    	for (int i = 0; i < originalArray.length; i++) {
    	    for (int j = 0; j < originalArray[i].length; j++) {
    	        if (originalArray[i][j] != 0) {
    	            count++;
    	            sparseArray[count][0] = i;
    	            sparseArray[count][1] = j;
    	            sparseArray[count][2] = originalArray[i][j];
    	        }
    	    }
    	}
    	// 输出稀疏数组
    	System.out.println("转换后的稀疏数组为:");
    	for (int i = 0; i < sparseArray.length; i++) {
    	    for (int j = 0; j < sparseArray[i].length; j++) {
    	        System.out.print(sparseArray[i][j] + "\t");
    	    }
    	    System.out.println();
    	}
    	System.out.println();
    	return sparseArray;
    }
    

    运行结果:

    转换后的稀疏数组为:
    12	12	11	
    2	4	1	
    2	5	1	
    3	4	1	
    3	5	1	
    3	6	2	
    3	7	2	
    4	5	2	
    4	6	1	
    5	5	1	
    5	6	2	
    5	7	2
    

    稀疏数组转换为二维数组

    private int[][] toOriginalArray(int[][] sparseArray) {
        // 初始化原始数组
        int[][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]];
        // 从第二个值开始,因为第一个值存的是原始数组的行列、有效值个数等信息
        for (int i = 1; i < sparseArray.length; i++) {
            // 由稀疏数组给原始数组赋值
            originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        System.out.println("转换后的二维数组为:");
        for (int i = 0; i < originalArray.length; i++) {
            for (int j = 0; j < originalArray[i].length; j++) {
                System.out.print(originalArray[i][j] + "\t");
            }
            System.out.println();
        }
        return originalArray;
    }
    

    实践运用

    在真实开发中,一般是将稀疏数组数据在数据库或者文件中进行保存,这里我使用 fastjson2 将稀疏数组转换成 JSON 字符串之后保存到电脑本地(二维数组转稀疏数组),再从本地读取文件内容进行解析(稀疏数组转二维数组)。保存到数据库也是同理的操作。

    保存到文件

    /**
     * 将JSON字符串保存为文件
     * @param jsonString 转换后的稀疏数组JSON字符串
     * @param fileName 电脑本地文件
     */
    private void toFile(String jsonString, String fileName) {
        File file = new File(fileName);
        FileWriter fileWriter = null;
        if (!file.exists()) {
            try {
                file.createNewFile();
                fileWriter = new FileWriter(file);
                char[] chars = jsonString.toCharArray();
                fileWriter.write(chars);
                fileWriter.flush();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            } finally {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    

    从文件读取并解析

    /**
     * 从文件读取内容
     * @param fileName
     * @return
     * @throws IOException
     */
    private String readFile(String fileName) throws IOException {
        File file = new File(fileName);
        FileReader reader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(reader);
        String line = null;
        System.out.println("文件读取内容为:");
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
            System.out.println();
            return line;
        }
        reader.close();
        bufferedReader.close();
        return line;
    }
    
    /**
     * 由JSON字符串转换成原始二维数组
     * @param jsonString
     * @return
     */
    private int[][] stringToOriginArray(String jsonString) {
        JSONArray objects = JSON.parseArray(jsonString);
        JSONArray s = (JSONArray) objects.get(0);
        // 初始化原始数组
        int[][] originalArray = new int[(int)s.get(0)][(int)s.get(1)];
        // 从第二个值开始,因为第一个值存的是原始数组的行列、有效值个数等信息
        for (int i = 1; i < objects.size(); i++) {
            JSONArray se = (JSONArray) objects.get(i);
            originalArray[(int)se.get(0)][(int)se.get(1)] = (int)se.get(2);
        }
        System.out.println("JSON字符串转换为二维数组:");
        for (int i = 0; i < originalArray.length; i++) {
            for (int j = 0; j < originalArray[i].length; j++) {
                System.out.print(originalArray[i][j] + "\t");
            }
            System.out.println();
        }
        return originalArray;
    }
    
  • 相关阅读:
    《数据库系统概论》王珊版课后习题
    C++之类与对象(2)
    金仓数据库KingbaseES sys_prewarm 扩展
    从 QFramework 重新开始
    个人云存储:使用Cpolar和极简主义文件管理器构建的公网访问平台
    交换机与路由器技术-06-路由器转发数据包封装过程
    《机器学习实战》学习笔记(十三)
    基于ADS的marx雪崩电路设计-设计实践(射频脉冲源)
    [Spring Cloud] gateway全局异常捕捉统一返回值
    Win11管理和优先处理通知的方法
  • 原文地址:https://www.cnblogs.com/wangms821/p/17524376.html