zoukankan      html  css  js  c++  java
  • 稀疏数组

    序言

    所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。

    应用

    可以使用稀疏数组来保留类似前面的二维数组(棋盘,地图等)

    把稀疏数组存盘,并且可以重新恢复原来的二维数组数。

    二维数组转稀疏数组

    1. 遍历二维数组,得到有效个数sum。
    2. 根据sum就可以创建稀疏数组sparseArr int[sum+1][3]
    3. 将二维数组的有效数据存入稀疏数组。

    稀疏数组转二维数组

    1. 先读取稀疏数组的第一行,根据第一行数据,创建原始的二维数组。
    2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组即可。

    代码实现

    package com.ddf.datastructure.sparsearray;
    
    import java.util.Random;
    
    /**
     * 稀疏数组
     *
     * 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
     *
     * 稀疏数组的处理方法是:
     * 记录数组一共有几行几列,有多少个不同的值
     * 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
     * 具体思路请参考下方代码实现
     *
     * 一个完整的二维数组转换为稀疏数组后的表现形式为:
     *
     * 0 0 0 0 0      (规则)    [原二维数组的行的长度] [原二维数组的列的长度] [原二维数组的有效数据(如int数组,非0即为有效)个数]
     * 1 0 0 0 2    ======>>    [原二维数组第一个有效元素的行角标] [原二维数组第一个有效元素的列角标] [原二维数组在这个坐标中的值]
     * 0 0 0 0 3
     *
     *   ||
     *   || 表现如下
     *  ||/
     *  3 5 3
     *  1 0 1
     *  1 4 2
     *  2 4 3
     *
     *  从上也可以看出,稀疏数组的行的大小由原二维数组有效数据的个数决定,所以如果原二维数组中的有效个数占比较大的话,使用稀疏数组,反而会增加大小
     *
     * @author dongfang.ding
     * @date 2019/6/11 14:01
     */
    public class SparseArray {
    
        public static void main(String[] args) {
    
            // 定义一个原始的二维数组,大小为10 * 10
            int[][] sourceArr = new int[10][11];
    
            // 给二维数组赋值,使有效(非零)的数组占少数部分,这样数组转换为稀疏数组才有意义
            Random random = new Random();
            sourceArr[0][0] = random.nextInt(10);
            sourceArr[1][2] = random.nextInt(10);
            sourceArr[3][3] = random.nextInt(10);
            sourceArr[8][9] = random.nextInt(10);
    
            System.out.println("====================原始数组========================");
            printArr(sourceArr);
            System.out.println("====================原始数组========================");
    
    
            System.out.println("====================稀疏数组数组========================");
            int[][] sparseArr = toSparse(sourceArr);
            printArr(sparseArr);
            System.out.println("====================稀疏数组数组========================");
    
    
            System.out.println("====================还原稀疏数组========================");
            int[][] toSourceArr = toSource(sparseArr);
            printArr(toSourceArr);
            System.out.println("====================还原稀疏数组========================");
    
        }
    
        /**
         * 将一个原始数组转换为稀疏数组
         * 稀疏数组的固定为三列,行号为原始数组有效数组的个数+1,因为第一行第一列用来存储原始数组的行数,第一行第二列存储原始数组的列数,
         * 第一行第三列用来存储原始数组的有效个数,从第二行开始记录有效数据在原始数组中的有效坐标以及值是多少,所以稀疏数组的大小为[原始数字有效值的个数][3]
         * @param sourceArr 原始数组
         */
        public static int[][] toSparse(int[][] sourceArr) {
            // 先统计原始数组的有效个数
            int validNum = 0;
            // 获得原始二维数组的行长
            int rowLength = sourceArr.length;
            // 获得原始二维数组的列长
            int colLength = 0;
            for (int[] ts : sourceArr) {
                for (int t : ts) {
                    colLength = ts.length;
                    if (t != 0) {
                        validNum++;
                    }
                }
            }
            System.out.printf("原始二维数组的大小为[%d][%d]", rowLength, colLength);
            System.out.println();
    
            // 统计出来有效个数后就可以确定稀疏数组的大小
            int[][] sparseArr = new int[validNum + 1][3];
            // 稀疏数组的0行0列存储原始二维数组的长度
            sparseArr[0][0] = rowLength;
            // 稀疏二维数组的0行1列存储原始二维数组的列长
            sparseArr[0][1] = colLength;
            // 稀疏二维数组的0行2列存储原始二维数组的有效个数
            sparseArr[0][2] = validNum;
    
    
            // 再次遍历原始二维数组,将有效数据放入稀疏数组中
            // 稀疏数组的第[0]行用来存储上述数据了,所以有效数据从第[1]列开始存储
            int row = 1;
            for (int i = 0; i < rowLength; i ++) {
                for (int j = 0; j < colLength; j ++) {
                    if (sourceArr[i][j] != 0) {
                        // 第一列存储原始数组有效数据的行号
                        sparseArr[row][0] = i;
                        // 第二列存储原始数组有效数据的列
                        sparseArr[row][1] = j;
                        // 第三列存储原始数组的值
                        sparseArr[row][2] = sourceArr[i][j];
                        // 稀疏数组没存储一个有效值需要一行三列,所以存储一个行号就要+1
                        row ++;
                    }
                }
            }
            return sparseArr;
        }
    
    
        /**
         * 打印二维数组
         * @param sourceArr
         */
        public static void printArr(int[][] sourceArr) {
            for (int[] ints : sourceArr) {
                for (int item : ints) {
                    System.out.printf("%d	", item);
                }
                System.out.println();
            }
        }
    
        /**
         * 将稀疏数组还原成
         * @param sparseArr
         * @return
         */
        public static int[][] toSource(int[][] sparseArr) {
            // 先还原原数组大小, 稀疏数组的第一行第一列为原始数组的行,第一行第二列为原始数组的列
            int[][] sourceArr = new int[sparseArr[0][0]][sparseArr[0][1]];
    
            // 稀疏数组从第[1]行开始为原始二维数组有效数据
            for (int i = 1; i < sparseArr.length; i ++) {
                // sparseArr[i][0]原始数组的行坐标,sparseArr[i][1]原始数组的列坐标,sparseArr[i][2]原始数组的值
                sourceArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
            }
            return sourceArr;
        }
    }
    View Code

    资料 

    https://www.jianshu.com/p/15dce86ffbfa

  • 相关阅读:
    LeetCode——二叉搜索树中的中序后继 II
    一加 2020.10.13 笔试
    携程 2020.10.13 笔试
    中科曙光 2020.10.12 面试
    58 2020.10.11 笔试
    华为 2020.10.11 面试
    LeetCode——二叉搜索树中的顺序后继
    健网未来 2020.10.10 面试
    波特率
    PGA基础知识极简教程(4)从FIFO设计讲起之异步FIFO篇
  • 原文地址:https://www.cnblogs.com/cnki/p/12111209.html
Copyright © 2011-2022 走看看