稀疏数组的实现原理及应用场景

稀疏数组

引子:

下图是一个11行11列的围棋棋盘,使用二维数组展示出来,此时用户要保存该棋局,有两种方式存储该棋局,第一种是使用该二维数组原封不动的存储到磁盘中,第二种方式是将其转换为稀疏数组存储到磁盘中,当下次打开时再将该稀疏数组还原为二维数组。

稀疏数组的实现原理及应用场景

稀疏数组的原型图:

稀疏数组的实现原理及应用场景

说明:

第一行:第1列代表原始二维数组有几行,第2列代表原始二维数组有几列,第3列代表原始二维数组中与初始值不相同的元素有几个(在本例子中表示黑子和白子的总数量是多少个?)

第二行:第1列代表第一个与初始值不相同的元素所在的行,第2列代表第一个与初始值不相同的元素所在的列,第3列代表第一个与初始值不相同的元素的值。

第三行:与第二行相类似

……

该稀疏数组的第一行的第3列的值 + 1就是该稀疏数组的行数,稀疏数组的列数固定为三列。

实现思路:

一、由原始二维数组转换为稀疏数组的思路:

1 遍历原始二维数组,统计出与默认值不相同的元素的个数num

2 创建稀疏数组,其为[num+1]行,[3]列的一个二维数组

3 稀疏数组的第一行的三个值分别为原始二维数组的行、列、[num]

4 再次遍历原始二维数组,将与原始值不相同的元素依次存入到稀疏数组的第二行到第[num+1]行。每一行的第1列存的是该元素所在行的索引,第2列存的是该元素所在列的索引,第3列存的是该元素的值。

二、由稀疏数组还原为原始二维数组的思路:

1 取出稀疏数组的第一行的第1列和第2列的值,分别为原始二维数组的行和列的个数,然后创建二维数组。

2 从第二行开始遍历稀疏数组,并还原为整个原始的二维数组。每一行的第1列为该元素在原始二维数组中的行的索引,第2列为该元素在原始二维数组中的列的索引,第3列为该元素的值。

代码实现:

public class ArithmeticChess {
    @Test
    public void testChess(){
        int length = 11;
        int[][] arrChess1 = new int[length][length];
        System.out.println("=================原始数组===============");
        arrChess1[5][5] = 1;
        arrChess1[5][7] = 2;
        arrChess1[6][6] = 1;
        int sum = 0;
        for (int[] arr : arrChess1) {
            for (int i : arr) {
                System.out.printf("%3d",i);
                if (i != 0){
                    sum++;
                }
            }
            System.out.println();
        }
        System.out.println("=================稀疏数组===============");
        int[][] sparse = new int[sum + 1][3];
        sparse[0][0] = length;
        sparse[0][1] = length;
        sparse[0][2] = sum;
        int count = 0;
        for (int i = 0; i < arrChess1.length; i++) {
            for (int j = 0; j < arrChess1[i].length; j++) {
                if (arrChess1[i][j] != 0){
                    count++;
                    sparse[count][0] = i;
                    sparse[count][1] = j;
                    sparse[count][2] = arrChess1[i][j];
                }
            }
        }
        for (int[] arr : sparse) {
            for (int i : arr) {
                System.out.printf("%3d",i);
            }
            System.out.println();
        }
        System.out.println("=================稀疏数组转换原始数组===============");
        int[][] arrChess2 = new int[sparse[0][0]][sparse[0][1]];
        for (int i = 1; i < sparse.length; i++) {
            arrChess2[sparse[i][0]][sparse[i][1]] = sparse[i][2];
        }
        for (int[] arr : arrChess2) {
            for (int i : arr) {
                System.out.printf("%3d",i);
            }
            System.out.println();
        }

    }
}

测试输出结果:

=================原始数组===============
  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  1  0  2  0  0  0
  0  0  0  0  0  0  1  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
=================稀疏数组===============
 11 11  3
  5  5  1
  5  7  2
  6  6  1
=================稀疏数组转换原始数组===============
  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  1  0  2  0  0  0
  0  0  0  0  0  0  1  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

稀疏数组的应用场景:

1 棋盘存储

2 矩阵存储

源码地址:

https://gitee.com/wang-hailei/arithmetic/tree/main

上一篇:Image Super-Resolution via Sparse Representation--Notes(Updating)


下一篇:词数统计及其重要程度统计