从一个场景来分析,为什么需要稀疏数组!
二维数组
我们以一个二维数组模拟五子棋为例,用二维数组模拟创建一个棋盘,数字1代表黑子,二代表白子。在某些场景下,我们需要保存游戏的进度,如果采用原始的二维数组的方式进行保存的话,我们可以看见存储量是非常大的。
所以,当我们采用稀疏数组进行存储后是这个样子的:
我们可以看出稀疏数组给我们节约了相当一部分的空间。
定义
稀疏数组也是一个数组,可以把它看成是一个普通数组的压缩。(一般情况下我们认为如果一个数组的无效数据量远大于有效数据的情况下,对数组进行压缩)
稀疏数组的存储
第一列 | 第二列 | 第三列 |
---|---|---|
原始数组的行数 | 原始数组的列数 | 原始数组有效数据的个数 |
原始数组非零位所作在行索引 | 原始数组非零位所在列索引 | 原始数组非零位的值 |
拿上述五子棋的例子来说:
原始二维数组,一共拥有11行,11列,有效数据的个数为2个
原始数组的第二行,第三列有一个有效数据1,它所对应的行索引为1,列索引为2,值为1。所以在稀疏数组中的存储为
11 | 11 | 2 |
---|---|---|
1 | 2 | 1 |
2 | 3 | 2 |
这样就将原始的二维数组压缩成了一个稀疏数组!
代码实现
1、创建一个二维数组
//创建一个原始的二维数组 11*11
//0:没有棋子,1:表示黑子,2:白子
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();
}
执行后的结果:
2、将二维数组转换成稀疏数组
2.1 遍历二维数组,获得有效数据的个数
//1、先遍历二维数组,得到非0数据的个数
int sum=0;
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j]!=0){
sum++;
}
}
}
System.out.println("sum="+sum);
得到的结果:
2.2创建对应的稀疏数组
//2、创建对应的稀疏数组
int sparseArray[][]=new int[sum+1][3];
//给稀疏数组赋值
sparseArray[0][0]=11;
sparseArray[0][1]=11;
sparseArray[0][2]=sum;
2.3向稀疏数组中存入数据
//遍历二维数组,将非0的值存放到稀疏数组中
int count=0; //count用于记录是第几个非零数据
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j]!=0){
count++;
sparseArray[count][0]=i;
sparseArray[count][1]=j;
sparseArray[count][2]=chessArr1[i][j];
}
}
得到的稀疏数组为:
3、将稀疏数组还原成为二维数组
3.1思路
- 从稀疏数组的第一行可以得到原始数组的行数和列数,创建一个二维数组
- 遍历稀疏数组,从其后几行的数据,可以得到原始数组有效数据的所在行所在列以及值,将其放入原始数组即可
//1、先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组
int chessArr2[][]=new int[sparseArray[0][0]][sparseArray[0][1]];
//2、读取稀疏数组的后几行的数据(从第二行开始),并赋值给原始的二维数组
for (int i = 1; i <sparseArray.length; i++) {
chessArr2[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
}