1.数据结构-稀疏数组

稀疏数组

如果一个数组(或者多维)中有大量的重复元素,可以使用稀疏数组来保存,以达到节约空间的目的。

稀疏数组的创建过程

  1. 稀疏数组的第一行表示数组几行几列(各个维度的长度)最后一位表示有效值个数

    // 如一个二维数组int[5][5] 其他大部分为默认值0只有3个赋值了
    // 则稀疏数组第一行为 5 5 3
    // 如是多维数组如int[5][5][7] 则第一行为 5 5 7 3

  2. 稀疏数组除第一行之后的行表示了每一个有效数组的坐标和值

    //例如一个二维数组 arr = int[3][3]
    // arr[0][3]=1 arr[2][2]=1
    //转成稀疏数组样子为
    // 3 3 2 //各维度长度和有效值个数
    // 0 3 1 // 具体有效值的坐标 最后一位为值
    // 2 2 1

1.数据结构-稀疏数组_第1张图片

代码实现

将数组转成稀疏数组的步骤

  1. 遍历数组获取到有效数据的个数
  2. 根据原数组的维度信息和有效信息个数就可以初始化一个稀疏数组 和稀疏数组第0行的具体值
  3. 再次遍历原数组将有效值的具体坐标和值存入稀疏数组

将稀疏数组转成原数组

  1. 将稀疏数组第0行取出 获取到原数组的维度信息和有效值个数
  2. 根据取出的原数组维度信息初始化原数组
  3. 从稀疏数组第1行开始一直遍历获取到所有有效值的坐标和具体值回填原数组

这里以最简单的二维数组为例

public class SparseArrayDemo {

    public static void main(String[] args) {
        // 原数组 是一个11*11 的数组
        int[][] originalArr = new int[11][11];
        // 分别存放3个数据其他用默认值0
        originalArr[0][3] = 1;
        originalArr[0][4] = 2;
        originalArr[4][6] = 1;
        printArr(originalArr);
        System.out.println("=================================");
        // 构建稀疏数组
        /**
         * 稀疏数组用第一列来分别表示 行 列 值
         *     row  column  value
         *     11   11      3       // 该数组有11行 11列 有3个有效值 其他都是可以忽略的默认值0
         *     0    3       1       // 后三行分别表示了 值的行 列 具体的值
         *     0    4       2
         *     4    6       1
         * 将一个11*11的大数组 压缩成了一个4*3 的稀疏数组 节约了空间
         */
        int[][] sparseArray = transferToSparseArray(originalArr);
        printArr(sparseArray);

        System.out.println("=================================");
        int[][] unfoldArrary = unfoldSparseArray(sparseArray);
        printArr(unfoldArrary);
        System.out.println("=================================");


    }

    private final static int INVALID_DATA = 0;

    /**
     * 把稀疏数组还原成原始数组
     *
     * @param sparseArr
     * @return
     */
    private static int[][] unfoldSparseArray(int[][] sparseArr) {
        // 1.通过稀疏数组的第一行 获取原数组一共有几行几列几个有效数据
        int row = sparseArr[0][0];
        int column = sparseArr[0][1];
        int validValueSum = sparseArr[0][2];

        // 2. 根据获取到的行和列初始原数组的大小
        int[][] originalArr = new int[row][column];

        // 遍历0行之后的所有行将数组具体的值填回原数组
        for (int i = 1; i <= validValueSum; i++) {
            int[] ints = sparseArr[i];
            originalArr[ints[0]][ints[1]] = ints[2];
        }
        return originalArr;
    }

    /**
     * 将数组转成稀疏数组
     *
     * @param originalArr
     * @return
     */
    private static int[][] transferToSparseArray(int[][] originalArr) {
        // 1.计算出一共有多少个有效数据
        int validDataSum = 0;
        for (int[] in : originalArr) {
            for (int i : in) {
                if (i != INVALID_DATA) {
                    validDataSum++;
                }
            }
        }
        // 2.获取到有多少有效数据之后 确定了稀疏数组到底有多少行
        int[][] sparseArr = new int[validDataSum + 1][3];
        // 3. 遍历找到所有有效数据填到具体的稀疏数组中
        sparseArr[0][0] = 11;
        sparseArr[0][1] = 11;
        sparseArr[0][2] = validDataSum;
        int validNumber = 1;
        for (int i = 0; i < originalArr.length; i++) {
            int[] in = originalArr[i];
            for (int j = 0; j < in.length; j++) {
                int val = in[j];
                if (val != INVALID_DATA) {
                    sparseArr[validNumber][0] = i;
                    sparseArr[validNumber][1] = j;
                    sparseArr[validNumber][2] = val;
                    validNumber++;
                }
            }
        }
        return sparseArr;
    }

    /**
     * 数组打印
     *
     * @param arr
     */
    private static void printArr(int[][] arr) {
        for (int[] in : arr) {
            for (int i : in) {
                System.out.printf("%d\t", i);
            }
            System.out.println();
        }
    }
}

你可能感兴趣的:(数据结构)