稀疏数组
基本介绍:当一个数组中大部分元素为0,或者是同一个值的数组时,可以使用稀疏数组来保存该数组
应用场景
如下我们用来表示一个棋盘,1,2表示在该位置的落子分别是白色和黑色,那么可以看到,此时棋盘上的大部分位置是还没落子的,如果我们进行存盘操作,就需要将该二维数组全部保存起来,显然很耗费资源,那么我们就可以将这个二维数组转换为稀疏数组来进行保存
0 0 0 0 0 0 0 0 0 0 0
0 0 2 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 2 0 0 0 0
0 0 0 1 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 0 0 0 0 0 0 0
转换为稀疏数组后是这样的
11 11 4
6 3 1
5 6 2
2 0 2
1 2 2
稀疏数组sparseArray中,第一行第一列表示了原始数组的行数,第一行第二列表示了原始数组的列数,第一行第三列表示了原始数组的有效值个数。从第二行开始,第一列表示有效值在原始数组中的行标,第二列表示有效值在原始数组中的列标,第三列表示有效值。所以可以总结出来,稀疏数组的初始化大小公式为
//sum为原始数组中的有效值个数
int[][] spareArray=new int[sum+1][3]
代码实现
原始数组转稀疏数组
1.确定原始数组的有效值个数
2.初始化稀疏数组
3.再一次遍历原始数组拿到有效值得位置
稀疏数组转原始数组
1.通过第一行的第一列,第二列可以初始化好原始数组
2.在从第二行开始遍历,第一列就是有效值在原始数组中的行标,第二列就是有效值在原始数组中的列表,第三列就是有效值
/**
* 将原始数组转换为稀疏数组
* @param array 原始数组
* @return 转换后的稀疏数组
*/
public static int[][] conversionToSparseArray(int[][] array){
int effective=0;
//得到原始二维数组的有效个数,从而确定稀疏数组的行数
for(int[] row:array){
for (int data:row){
if(data!=0){
effective++;
}
}
}
int[][] sparseArray=new int[effective+1][3];
//稀疏数组的的第一行存储原始数组的相关信息
sparseArray[0][0]= array.length;
sparseArray[0][1]=array[0].length;
sparseArray[0][2]=effective;
for(int i=0;i< array.length;i++){
for(int j=0;j<array[0].length;j++){
if(array[i][j]!=0){
//注意理解使用有效个数来暂定放入的行,实际上从稀疏数组的从下往上赋值,即第一个有效数字放在了稀疏数组的最后一行,依次类推
sparseArray[effective][0]=i;
sparseArray[effective][1]=j;
sparseArray[effective][2]=array[i][j];
effective--;
}
}
}
return sparseArray;
}
/**
* 转换稀疏数组为原始数组
* @param sparseArray 稀疏数组
* @return 原始数组
*/
public static int[][] conversionToArray(int[][] sparseArray){
//从稀疏数组的第一行中获取到原始数组的信息
int rowSum=sparseArray[0][0];
int colSum=sparseArray[0][1];
int[][] array=new int[rowSum][colSum];
//第二行开始遍历稀疏数组中的值放入到原始数组中
for(int i=1;i< sparseArray.length;i++){
int row=sparseArray[i][0];
int col=sparseArray[i][1];
int number=sparseArray[i][2];
array[row][col]=number;
}
return array;
}
完整代码实现
public class SparseArrayTest {
private static final Random RANDOM=new Random(2);
/**
* 数组打印工具方法
* @param array 需要打印的数组
*/
public static void print(int[][]array){
for(int[] row:array){
for (int data:row){
System.out.printf("%d\t",data);
}
System.out.println();
}
}
/**
* 创建随机赋值的二维数组
* @param row 行数
* @param col 列数
* @param effective 数组有效值个数
* @return 初始化完成的二维数组
*/
public static int[][] randomArray(int row,int col,int effective){
int[][] array=new int[row][col];
for(int i=0;i<effective;i++){
int randomRow= RANDOM.nextInt(row);
int randomCol=RANDOM.nextInt(col);
int randomNumber=RANDOM.nextInt(3);
array[randomRow][randomCol]=randomNumber;
}
return array;
}
/**
* 将原始数组转换为稀疏数组
* @param array 原始数组
* @return 转换后的稀疏数组
*/
public static int[][] conversionToSparseArray(int[][] array){
int effective=0;
//得到原始二维数组的有效个数,从而确定稀疏数组的行数
for(int[] row:array){
for (int data:row){
if(data!=0){
effective++;
}
}
}
int[][] sparseArray=new int[effective+1][3];
sparseArray[0][0]= array.length;
sparseArray[0][1]=array[0].length;
sparseArray[0][2]=effective;
for(int i=0;i< array.length;i++){
for(int j=0;j<array[0].length;j++){
if(array[i][j]!=0){
//注意理解使用有效个数来暂定放入的行,实际上从稀疏数组的从下往上赋值
sparseArray[effective][0]=i;
sparseArray[effective][1]=j;
sparseArray[effective][2]=array[i][j];
effective--;
}
}
}
return sparseArray;
}
/**
* 保存稀疏数组到磁盘中
* @param array 需要保存的稀疏数组
* @param path 文件路径
*/
public static void saveSparseArray(int[][] array,String path){
File file=new File(path);
//使用对象流将稀疏数组写入磁盘
try(ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream(file))){
objectOutputStream.writeObject(array);
objectOutputStream.flush();
}
catch(IOException e){
e.printStackTrace();
}
}
/**
* 解析磁盘中的数据为原始稀疏数组
* @param path 文件路径
* @return 解析后的稀疏数组
*/
public static int[][] parseSparseArray(String path){
File file=new File(path);
try(ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(file))
){
Object data=objectInputStream.readObject();
if(data instanceof int[][]){
return (int[][])data;
}
}catch(IOException |ClassNotFoundException e){
e.printStackTrace();
}
return null;
}
/**
* 转换稀疏数组为原始数组
* @param sparseArray 稀疏数组
* @return 原始数组
*/
public static int[][] conversionToArray(int[][] sparseArray){
int rowSum=sparseArray[0][0];
int colSum=sparseArray[0][1];
int[][] array=new int[rowSum][colSum];
for(int i=1;i< sparseArray.length;i++){
int row=sparseArray[i][0];
int col=sparseArray[i][1];
int number=sparseArray[i][2];
array[row][col]=number;
}
return array;
}
public static void main(String[] args) {
int[][] array=ArrayUtil.randomArray(11,11,5);
System.out.println("-------------原始数组-----------");
print(array);
System.out.println("-------------稀疏数组-----------");
int[][] sparseArray=conversionToSparseArray(array);
print(sparseArray);
//保存路径,根据自身需求决定
String path="D:\\桌面\\笔记\\数据结构和算法\\Practice\\Practice\\DataStructures\\src\\main\\resources\\sparseArray.txt";
saveSparseArray(sparseArray,path);
int[][] parseSparseArray=parseSparseArray(path);
System.out.println("-------------文件解析到的稀疏数组-----------");
print(parseSparseArray);
System.out.println("-------------文件解析到的稀疏数组转换为原始数组-----------");
int[][] parseArray=conversionToArray(parseSparseArray);
print(parseArray);
}
}
测试结果
-------------原始数组-----------
0 0 0 0 0 0 0 0 0 0 0
0 0 2 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 2 0 0 0 0
0 0 0 1 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 0 0 0 0 0 0 0
-------------稀疏数组-----------
11 11 4
6 3 1
5 6 2
2 0 2
1 2 2
-------------文件解析到的稀疏数组-----------
11 11 4
6 3 1
5 6 2
2 0 2
1 2 2
-------------文件解析到的稀疏数组转换为原始数组-----------
0 0 0 0 0 0 0 0 0 0 0
0 0 2 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 2 0 0 0 0
0 0 0 1 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 0 0 0 0 0 0 0