1.稀疏数组使用场景
1.数据稀疏性较高的情况:当大部分元素的值相同或为默认值(如 0),而只有少数元素具有不同的值时,使用稀疏数组可以节省存储空间。
2. 大规模矩阵运算:在处理大规模的矩阵数据时,如果矩阵中存在大量的零元素,使用稀疏数组能显著减少存储和计算开销。
3. 游戏开发:例如表示地图或棋盘上的状态,其中大部分位置可能是空的。
如图:
2.稀疏数组演示
1.当我们用普通二维数组存储大部分元素为0时如图:
可能会造成以下问题:
存储空间浪费:大量的 0 元素占据了不必要的存储空间,导致内存使用效率低下。
访问和操作效率降低:在遍历数组进行读取、修改或其他操作时,需要处理大量无意义的 0 元素,增加了不必要的计算开销,从而降低了程序的执行效率。
数据传输和存储成本增加:如果需要在网络中传输或持久化存储这样的数组,大量的 0 元素会增加传输的数据量和存储的空间需求,导致成本上升。
2.转化为稀疏数组时如图:
此时我们就将普通数组中的非0数值记录在稀疏数组中,从而简化了数组,空间利用效率大大提升,提高了运算效率。
3.稀疏数组转化
1.原理
稀疏数组的列数是固定的,为三列,分别为行数,列数,值。
第一行代表的是普通二维数组的总行数与总列数,即是一个几乘几的矩阵,后面的值代表非零元素的个数。
第二行即以后,分别指的是非零元素的行,列,以及对应非零元素对应的值,而且有几个非零数值就有几行(在第一行之后)。
2.思路
既然要求数组中非零的值的个数,那么就要遍历数组求出值的个数,在表示出值的行数与列数,并且在初始化稀疏数组时要知道这个二维数组的行数,并将普通二维数组中的值以及对应的行和列放入稀疏数组中。
3.实现稀疏数组的步骤
1.创建一个二维数组,并用增强循环实现遍历
2.遍历这个二维数组,得出非零数据的个数
3.创建对应的稀疏数组,列数为3列,行数要根据非零数值的个数来表示
4.将非零数值的行列,以及它本身的值赋值给稀疏数组对应的位置中去
5.实现稀疏数组转普通数组
4.稀疏数组算法实现
1.创建一个二维数组,并用增强循环实现遍历
小编这里使用的是增强循环方式遍历的二维数组,外层的增强 for 循环中,每次迭代会将二维数组中的一行(一维数组)赋值给 row ,然后内层的增强 for 循环再遍历 row 中的每个元素。这样就可以方便地遍历二维数组中的所有元素。
int chessArr[][]=new int[5][5]; //创建一个二维数组
chessArr[1][1]=1; //对其中两个进行赋值
chessArr[2][2]=2;
for(int row[]:chessArr){ //增强循环
for (int data:row){
System.out.printf("%d ",data);
}
System.out.println(); //每行遍历后换行
}
小编这里使用的是 printf ,不是println哟。
2.遍历这个二维数组,得出非零数据的个数
这里小编使用了两个循环,来一个个遍历二维数组的值,若值不等于0,那么非零数值加一。
int sum=0;
for (int i = 0; i <5 ; i++) {
for (int j = 0; j < 5; j++) {
if (chessArr[i][j]!=0){
sum++;
}
}
}
System.out.println(sum); //测试非0的值的个数
3.创建对应的稀疏数组,列数为3列,行数要根据非零数值的个数来表示。
在稀疏数组中所有的列数都为3列,且行数得根据对应的非零的值的个数来表示,并且数值对应的行列要在第二行开始,所以行数为对应非零数组加一。
int sparseArr[][]=new int[sum+1][3]; //这里的行根据非零个数来决定
4.将非零数值的行列,以及它本身的值赋值给稀疏数组对应的位置中去。
小编这里使用的否循环遍历二维数组,将非零数的行,列,值赋值给对应的稀疏数组,并且用一个变量来表示稀疏数组的行,所以每次循环都要加一,即一行赋值完成后进行第二行的赋值,0,1,2,表示的是稀疏数组的行,列,值。
sparseArr[0][0]=5; //第一行的几列进行赋值
sparseArr[0][1]=5;
sparseArr[0][2]=sum;
int index=1;
for (int i = 0; i <5 ; i++) {
for (int j = 0; j <5 ; j++) {
if (chessArr[i][j]!=0){ //将不为0的数从第2行遍历
sparseArr[index][0]=i;
sparseArr[index][1]=j;
sparseArr[index][2]=chessArr[i][j];
index++; //下次循环从第3行开始遍历
}
}
}
5.实现稀疏数组转普通数组。
在转化为普通数组时,普通二维数组的行列总数分别等于稀疏数组的第一行第一列与第一行第二列。再求对应的数值时要在稀疏数组中找到对应的行数,与列数。小编这里从稀疏数组的第一行开始来的输出对应普通二维数中对应值的行数与列数。
int chessArr2[][]=new int[sparseArr[0][0]][sparseArr[0][1]];
//稀疏数组的第一行就是代表的普通数组的行列
for (int i = 1; i <sum+1 ; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2];
//列数一定,行数进行循环
}
6.最后代码如下:
public class SparseArr {
public static void main(String[] args) {
int chessArr[][]=new int[5][5]; //创建一个二维数组
chessArr[1][1]=1; //对其中两个进行赋值
chessArr[2][2]=2;
for(int row[]:chessArr){ //增强循环
for (int data:row){
System.out.printf("%d ",data);
}
System.out.println(); //每行遍历后换行
}
//遍历非零数据的个数
int sum=0;
for (int i = 0; i <5 ; i++) {
for (int j = 0; j < 5; j++) {
if (chessArr[i][j]!=0){
sum++;
}
}
}
System.out.println(sum); //测试非0的值的个数
/*创建对应的稀疏数组(sparseArr)*/
int sparseArr[][]=new int[sum+1][3]; //这里的行根据非零个数来决定
sparseArr[0][0]=5; //第一行的几列进行赋值
sparseArr[0][1]=5;
sparseArr[0][2]=sum;
int index=1;
for (int i = 0; i <5 ; i++) {
for (int j = 0; j <5 ; j++) {
if (chessArr[i][j]!=0){ //将不为0的数从第2行遍历
sparseArr[index][0]=i;
sparseArr[index][1]=j;
sparseArr[index][2]=chessArr[i][j];
index++; //下次循环从第3行开始遍历
}
}
}
/*输出稀疏数组*/
for (int row[]:sparseArr){
for (int data:row){
System.out.printf("%d ",data);
}
System.out.println();
}
/*实现稀疏数组变为普通数组*/
int chessArr2[][]=new int[sparseArr[0][0]][sparseArr[0][1]];
//稀疏数组的第一行就是代表的普通数组的行列
for (int i = 1; i <sum+1 ; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2]; //列数一定,行数进行循环
}
/*输出普通数组*/
for(int row[]:chessArr2){
for (int data:row) {
System.out.printf("%d ",data);
}
System.out.println();
}
}
}
7.输出结果:
二维数组表示:
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 0
0 0 0 0 0
非零值的个数2
稀疏数组展示:
5 5 2
1 1 1
2 2 2
稀疏数组的还原展示:
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 0
0 0 0 0 0
5.总结
小编认为实现稀疏数组的主要是要明白在稀疏数组中对应行与列代表的意义,以及要熟练运用循环遍历等知识。当然限于小编能力有限,再解释时难免有些问题,以及代码调试存在某些问题,欢迎个位uu能给我提出宝贵意见。
看到这里了,如果觉得小编的代码以及讲解有用的话,就请给小编一个小小的赞来鼓励一下吧。