数据结构与算法(1)| 青训营笔记

623 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的的第12天

1.2 稀疏数组

1.2.1 使用场景

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

1.2.2 记录方法及作用

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同元素的行列及值记录在一个小规模的数组中,从而减少内存的占用空间

1.2.3 示意图

image.png

上图详解

(1):右侧稀疏数组的第一行表示左边二维数组共多少行多少列,一共有多少个值

(2):[1]~[9]表示元素(不分先后),如 [1] 所代表的元素在二维数组中是3,3位于二维数组的第0行第3列,以此类推 [2] ~ [9] ,最终得出完整的稀疏数组

1.2.4 代码实现

    //创建一个二维数组11*11
    //0表示没有棋子,1表示黑子,2表示蓝子
    public static void main(String[] args) {
        int chessArr1[][] = new int[11][11];
        chessArr1[1][2] = 1;
        chessArr1[2][3] = 2;
        System.out.println("这是原始的二维数组");
        for (int[] row : chessArr1) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }

上方代码详解

(1)程序的第二行即创建一个名为chessArr1且11 x 11的二维数组

(2)程序的第三、四行分别执行复制操作(因数组只进行初始化,故在赋值操作执行之前均为0),第三行表示在chessArr1的第2行第3列把1赋值给0,故该数组的第2行第3列值为1,chessArr1[2][3]同理

(3)第6行采用增强for循环定义一个row数组来接收该数组改变后的值,根据增强for循环的定义,此时需要额外定义一个变量用于存储该二维数组中所有的值,最后格式化输出该二维数组

(4)因为是二维数组,考虑到格式化的问题,我们将输出流改写成 System.out.printf,后加上%d\t,以确保美观性,最终在一层for循环后使用System.out.println();强制换行,起到11 x 11的效果

int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (chessArr1[i][j] != 0) {
                    sum++;
                }
            }
        }
System.out.println(sum);

上方代码详解

(1)程序的第一行定义一个sum变量用于存储二维数组里面非0值的个数

(2)程序的第二、三行使用双层for循环来遍历二维数组(这一动作可以理解为全盘扫描)

(3)程序的第四行代码的意思即如果chessArr1这一数组的第[i]行第[j]列的数值不为0,就把这个数值记录下来

(4)程序的第五行代码的意思即当遍历到二维数组chessArr1数组中有非0数值,即记录个数,最终使用System.out.println();打印输出二维数组中非0值的个数

   int spaceArr[][] = new int[sum + 1][3];
        spaceArr[0][0] = 11 ;
        spaceArr[0][1] = 11 ;
        spaceArr[0][2] = sum;
        int count = 0 ;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (chessArr1[i][j] != 0) {
                    count++;
                    spaceArr[count][0] = i ;
                    spaceArr[count][1] = j ;
                    spaceArr[count][2] = chessArr1[i][j];
                }
            }
        }
     System.out.println();

上方代码详解

(1)代码的第一行定义一个稀疏数组spaceArr[][],该数组初始化是即用sum初始化遍历即可,因sum代表的是二维数组中非0值的个数,根据下图可知image-20220803224032853

该稀疏数组spaceArr[][]的第一行是留给统计该二维数组基本信息的,又由于sum表示的是二维数组chessArr1[][]中非0值的个数,故不需要考虑位置(如+1问题,直接加上第一行的基本信息即可)

(2)代码的第二、三、四行分别对应上图第一行(带数字)的第二、三、四列,sum的个数即为稀疏数组spaceArr[][]的个数

(3)代码的第五行即定义一个count变量,count用来计二维数组中非0值的个数

(4)代码的第六、七行进行双层for循环遍历二维数组chessArr1[][],第八行判断在二维数组chessArr1在第[i]行第[j]列是否为空,如果不为空,记录count的个数并+1

(5)代码的第十、十一、十二行进行赋值操作,此时注意ij都是要+1,故在写代码的时候须进行-1的操作,此外,二维数组的列同理。spaceArr[i][j]即记录该二维数组所对应的位置的具体的值,最后进行换行处理

        System.out.println("得到的稀疏数组为如下形式");
        for (int i = 0; i < spaceArr.length; i++){
            System.out.printf("%d\t%d\t%d\t\n",spaceArr[i][0],spaceArr[i][1],spaceArr[i][2]);
        }
        System.out.println();
    }
}

上方代码详解

(1)代码第二行使用for循环遍历稀疏数组spaceArr的长度,第三行运用System.out.printf进行格式化输出

(2)格式化输出的时候注意稀疏数组的列是从0开始计算,否则会抛出数组下标越界等Exception

(3)循环过后强制换行,以达到上方图片中的效果