稀疏数组介绍:
稀疏数组:当一个数组中大部分元素为同一个值时,就可以考虑使用稀疏数组来保存数据节省空间。
稀疏数组的原理:
1)稀疏数组一共三列,第一行的第一列保存原二维数组的行数,第一行第二列保存原二维数组的列数,第一行第三列保存原二维数组非0数据的个数;
2)稀疏数组一共有【原二维数组非0个数+1】行,第一行保存原二维数组整体信息,其余行数保存非0数据的具体信息:第一列保存数据的行数,第二列保存数据的列数,第三列保存数据的值。
以下是两个数据图,我们将对这两个数组进行相互转换:
完整代码:
/**
* ClassName: SpareArray
* Package: datas
* Description:
*
* @Author 洛神
* @Create 2024/3/14 下午 11:46
* @vERSION 1.0
*/
public class SpareArray {
public static void main(String[] args) {
//创建一个原始的二维数组
//0:没有棋子;1:黑子;2:蓝子
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
//输出原始的二维数组
for (int[] row:chessArr1) {
for (int data:row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
//将二维数组转稀疏数组
//1.先遍历二维数组 得到非0数据的个数
int sum = 0;
for(int[] row:chessArr1){
for(int data:row){
if(data != 0){
sum++;
}
}
}
System.out.println(sum);
//2.
// 创建对应的稀疏数组
int sparseArr[][] = new int[sum+1][3];
//给稀疏数组赋值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = 2;
//遍历二维数组,将非0的值存放到稀疏数组
int loop=0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if(chessArr1[i][j]!=0){
loop++;
//因为列固定,行随非0数字的更新而不同,找到两者之间的规律建立联系
sparseArr[loop][0]=i;
sparseArr[loop][1]=j;
sparseArr[loop][2]=chessArr1[i][j];
}
}
}
System.out.println("==================================");
for (int i = 0; i < sparseArr.length; i++) {
System.out.println(sparseArr[i][0]+"\t"+sparseArr[i][1]+"\t"+sparseArr[i][2]);
}
//将稀疏数组恢复成二维数组
//1.先读取稀疏数组第一行的数据由此创建二维数组
int[][] td =new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
td[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2];
}
System.out.println("***********************************************");
for (int i = 0; i < td.length; i++) {
for (int j = 0; j < td[0].length; j++) {
System.out.printf("%d\t",td[i][j]);
}
System.out.println();
}
}
}
代码分析:
1.创建二维数组信息:
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
//输出原始的二维数组
for (int[] row:chessArr1) {
for (int data:row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
输出效果:
2.二维数组 ————> 稀疏数组
2.1二维数组的行列数知道,遍历二维数组找出非0数据的个数。创建稀疏数组。
这里使用了增强for循环。for(int[] row:chessArr1) 其中:int[]为循环的数据的数据类型,row为自定义变量名,chessArr1为要循环的数据
int sum = 0;
for(int[] row:chessArr1){
for(int data:row){
if(data != 0){
sum++;
}
}
}
2.2创建稀疏数组并给第一行赋值
稀疏数组的列数为三列是固定的。行数为非0数据的个数+1,因为第一行存放二维数组整体信息,其他每行对应非0数据的具体信息
稀疏数组第一行整体信息具体为:sparseArr[0][0]的值为二维数组的行数,sparseArr[0][1]的值为二维数组的列数,sparseArr[0][2]为二维数组非0数据的个数
// 创建对应的稀疏数组
int sparseArr[][] = new int[sum+1][3];
//给稀疏数组赋值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = 2;
2.3我们已经知道了二维数组非0数据的个数,现在我们要遍历二维数组找到非0数据的具体行列数信息存入稀疏数组。
2.3.1当第一个非0数据出现时,我们当然知道将信息保存在稀疏数组的第二行,但是在循环中,第二个、第三个、...数据出现时呢?这样操作只会不断更新稀疏数组第二行的数据,但之前非0数据的信息并未保存下来。因此,我们不能将数据存放的位置写死,要找出非0数据的位置信息与稀疏数组的位置信息的规律,将二者联系起来。
2.3.2当第一个非0数据出现时,我们将信息存放在稀疏数组的第二行,当第二个非0数据出现时,我们将信息存放在稀疏数组的第三行,以此类推...我们找出的规律是:将第n个出现的数据保存在稀疏数组的第n+1行
2.3.3我们要创建一个变量显示这是第几个非0数据,并且这个变量+1后也将成为稀疏数组的行数。
2.3.4赋值对应关系:第一个非0数据出现,loop+1,稀疏数组第2行的第1列保存第1个非0数据的行数,稀疏数组第2行的第2列保存第1个非0数据的列数,稀疏数组第2行的第3列保存第1个非0数据的值,至此,第一个非0数据信息保存完毕。当第二个非0数据出现,也根据上述关系保存。
3.5至此,稀疏数组创建并赋值完成。
int loop=0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if(chessArr1[i][j]!=0){
loop++;
//因为列固定,行随非0数字的更新而不同,找到两者之间的规律建立联系
sparseArr[loop][0]=i;
sparseArr[loop][1]=j;
sparseArr[loop][2]=chessArr1[i][j];
}
}
}
2.4.显示稀疏数组
方式1
for (int i = 0; i < loop+1; i++) {
for (int j = 0; j < 3; j++) {
System.out.printf("%d\t",sparseArr[i][j]);
}
System.out.println();
}
方式2
for (int i = 0; i < sparseArr.length; i++) {
System.out.println(sparseArr[i][0]+"\t"+sparseArr[i][1]+"\t"+sparseArr[i][2]);
}
运行效果:
3.稀疏数组 ——>二维数组
3.1先遍历稀疏数组得到创建二维数组的信息
for (int i = 0; i < sparseArr.length; i++) {
System.out.println(sparseArr[i][0]+"\t"+sparseArr[i][1]+"\t"+sparseArr[i][2]);
}
运行效果:
从稀疏数组的第一行信息中我们看出,它所代表的是一个11行1列有两个非0数据的二维数组。
3.2创建二维数组
由于默认初始化,因此不给二维数组遍历赋值,它里面的所有元素默认初始化为0
int[][] td =new int[sparseArr[0][0]][sparseArr[0][1]];
3.3给二维数组赋值
3.3.1从稀疏数组的第二行开始,根据规则把非0数据赋给二维数组。这里,两个数组的对应关系显得尤为重要。
3.3.2因为要赋值数据的个数是稀疏数组行数-1,所以我们用稀疏数组行数作为循环条件。
3.3.3规律:二维数组中要赋值的位置:行数:稀疏数组第1列;列数:稀疏数组第2列;值:稀疏数组第3列
3.3.4for循环中,i从1开始,因为第1行不存放具体数据信息【下标从0开始】;i<sparseArr.length;sparse.length为n,说明非0数据的个数为i-1,数组下标从0开始,那么第n个非0数据的信息正好在稀疏数组中下标为n的数据上。最后一个数据的下标为spare.length-1,设置循环条件为i<sparseArr.length,当i=sparseArr.length时跳出循环。
for (int i = 1; i < sparseArr.length; i++) {
td[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2];
}
3.4至此,稀疏数组转化二维数组完成,打印一下输出二维数组内容。
for (int i = 0; i < td.length; i++) {
for (int j = 0; j < td[0].length; j++) {
System.out.printf("%d\t",td[i][j]);
}
System.out.println();
}
显示效果: