稀疏数组
假设现在有一个如下的八行八列的二维数组:
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 2 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
先使用Java实现该数组:
package com.dh.array;
public class SparseArray {
public static void main(String[] args) {
//定义原始数组
int[][] oldArr = new int[8][8];
oldArr[1][2] = 1;
oldArr[2][3] = 2;
//打印原始数组
for (int[] ints : oldArr) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
我们可以看到,只有一个1,一个2,剩下的都是0,那我们能不能直接记录下1和2的位置,然后记录下剩下的都是0来缩小规模呢?
答案是可以的,我们可以使用稀疏数组来存储这类数据。
数组转换为稀疏数组存储格式:
1.定义一个二维数组(行数:存储数据+1,列数:3);
2.第一行存储的数据为:原始数组的行数,原始数组的列数,储存的值的个数;
3.每一行存储一个数据:数据的行数,数据的列数,值
以上述例子分析:
第一行数据:8,8,2 //八行,八列,存储两个值(1和2)
第二行数据:1,2,1 //第二行第三列的1(第二行下标为1,第三列下标为2,所以为1,2)
第三行数据:2,3,2 //第三行第四列的2
如何使用Java代码实现呢?
第一行的数据很简单
行数:二维数组.length;
列数:二维数组[0].length;
个数:遍历使用一个计数器计数即可。
首先要获取有效值的个数:
//首先要确定存储数据的个数用以确定稀疏数组的行数(个数+1)
int count = 0;
for (int i = 0; i < oldArr.length; i++) {
for (int j = 0; j < oldArr[i].length; j++) {
if(oldArr[i][j] != 0){
count++;
}
}
}
然后可以确定稀疏数组的行数(有效值的个数+1),列数固定为3,就可以声明一个稀疏数组并且分配空间了:
//声明稀疏数组并且分配空间
int[][] newArr = new int[count+1][3];
第一行的数据也可以确定了:
//确定稀疏数组的第一行数据
newArr[0][0] = oldArr.length;
newArr[0][1] = oldArr[0].length;
newArr[0][2] = count;
接着遍历原始数组,取得要存储的值,并且获取该值所在的行数和列数:
//确定第二行之后的数据
int num = 1; //用以确认行数,从第二行开始,下标为1
for (int i = 0; i < oldArr.length; i++) {
for (int j = 0; j < oldArr[i].length; j++) {
if(oldArr[i][j] != 0){ //要储存的值的条件
newArr[num][0] = i; //存储值所在的行数
newArr[num][1] = j; //存储值所在的列数
newArr[num][2] = oldArr[i][j]; //存储的值
num++; //记录完一行,行数加一
}
}
}
最后输出,验证一下结果:
结果一致!没有问题~
那稀疏数组怎么还原为原始的数组呢?
//稀疏数组还原为原始数组
int[][] oldArr1 = new int[newArr[0][0]][newArr[0][1]]; //通过稀疏数组的第一行的前两个数确定原始数组的行数和列数
for (int i = 1; i <= newArr[0][2]; i++) {//从稀疏数组的第二行开始为原始数组的值,数据个数从稀疏数组的第一行的第三个数确定
oldArr1[(newArr[i][0])][(newArr[i][1])] = newArr[i][2];//稀疏数组每行的第一、第二个数为原始数组的下标,第三个数为值
}
System.out.println("==========================");
System.out.println("稀疏数组还原:");
for (int[] ints : oldArr1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
还原结果也是正确的~
完整代码如下:
package com.dh.array;
public class SparseArray {
public static void main(String[] args) {
//1.定义原始数组
int[][] oldArr = new int[8][8];
oldArr[1][2] = 1;
oldArr[2][3] = 2;
//打印原始数组
System.out.println("原始数组:");
for (int[] ints : oldArr) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
//----------------------------------------------------------------------------------
//2.原始数组--->稀疏数组
//首先要确定存储数据的个数用以确定稀疏数组的行数(个数+1)
int count = 0;
for (int i = 0; i < oldArr.length; i++) {
for (int j = 0; j < oldArr[i].length; j++) {
if(oldArr[i][j] != 0){
count++;
}
}
}
//定义一个稀疏数组
int[][] newArr = new int[count+1][3];
//确定第一行的数据
newArr[0][0] = oldArr.length;
newArr[0][1] = oldArr[0].length;
newArr[0][2] = count;
//确定第二行之后的数据
int num = 1; //用以确认行数,从第二行开始,下标为1
for (int i = 0; i < oldArr.length; i++) {
for (int j = 0; j < oldArr[i].length; j++) {
if(oldArr[i][j] != 0){ //要储存的值的条件
newArr[num][0] = i; //存储值所在的行数
newArr[num][1] = j; //存储值所在的列数
newArr[num][2] = oldArr[i][j]; //存储的值
num++; //记录完一行,行数加一
}
}
}
System.out.println("==========================");
System.out.println("稀疏数组:");
//遍历稀疏数组
for (int[] ints : newArr) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
//------------------------------------------------------------------------------------
//3.稀疏数组--->原始数组
//通过稀疏数组的第一行的前两个数确定原始数组的行数和列数
int[][] oldArr1 = new int[newArr[0][0]][newArr[0][1]];
//从稀疏数组的第二行开始为原始数组的值,数据个数从稀疏数组的第一行的第三个数确定
for (int i = 1; i <= newArr[0][2]; i++) {
//稀疏数组每行的第一、第二个数为原始数组的下标,第三个数为值
oldArr1[(newArr[i][0])][(newArr[i][1])] = newArr[i][2];
}
System.out.println("==========================");
System.out.println("稀疏数组还原:");
for (int[] ints : oldArr1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
换来换去的话可能会有一点点绕,在写程序的时候尽量细心一点,如果不理解,可以拿纸笔写写画画一下,就很容易明白了。
若有错误,也请指出~