一、定义
首先是关于稀疏数组,什么是稀疏数组?在数学中有个叫稀疏矩阵的东西,稀疏矩阵的定义是在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵。
延申到数据结构中的稀疏数组时,如果一个数组中元素为0的数目远远大于非0元素的数目,那么将这个数组进行压缩之后得到的一个新的数组就是稀疏数组。再到实际应用中,如果一个数组中我们不想要的元素(可以为0,也可以不为0)远远大于我们想要的元素,那么我们也可以将这个数组进行压缩保存之后得到一个稀疏数组。
二、稀疏数组存在的意义
在上面中提到稀疏数组是由另一个数组进行压缩得到的,那么为什么要原本的数组进行压缩呢?
理由是原本的数组存在着大量无用的数组,真正有用的数据较少,如果用普通的数组进行保存,在数据序列化存储在磁盘中时,进行IO的效率会降低。而使用稀疏数组可以节省存储空间,避免了不必要的资源的浪费,提高了IO效率。
三、压缩存储的方式
1、普通的存储
第一行分别为原数组的行、列、有效数据个数
第二行之后分别为有效数据所在的行、列、有效数据值
如:
rows cols n
r1 c1 data1
......
rn cn datan
举个例子():
原数组为:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 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 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 4 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 3 0 0 0 0 0 0 0 0
进行压缩存储后得到的稀疏数组为:
11 11 4
1 2 1
2 4 2
8 2 4
10 2 3
代码以及相关注释如下:
/**
* 稀疏数组
* @author lhq
*
*/
public class SparseArray {
public static void main(String[] args) {
//有效数据个数
int sum=0;
//初始化数组
int array[][]= new int[11][11];
//有效数据
array[1][2]=1;
array[2][4]=2;
array[10][2]=3;
array[8][2]=4;
//统计有效数据个数
System.out.println("初始二维数组为:");
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[i].length;j++) {
System.out.print(array[i][j]+" ");
if(array[i][j]!=0)
sum++;
}
System.out.println();
}
//定义稀疏数组
int sparseArray[][]=new int[sum+1][3];
//记录行数
sparseArray[0][0] = array.length;
//记录列数
sparseArray[0][1] = array[0].length;
//记录有效数据个数
sparseArray[0][2] = sum;
//标识第几个
int count=1;
//记录对应数据
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[i].length;j++)
if(array[i][j]!=0) {
sparseArray[count][0]=i;
sparseArray[count][1]=j;
sparseArray[count][2]=array[i][j];
count++;
}
}
System.out.println("进行压缩存储之后的稀疏数组为:");
//输出稀疏数组
for(int i=0;i<sparseArray.length;i++) {
for(int j=0;j<sparseArray[i].length;j++)
System.out.print(sparseArray[i][j]+" ");
System.out.println();
}
}
}
然后就是从稀疏数组转换为普通的二维数组的过程,稀疏数组第一行的前两列就是普通二维数组的行列,第三列就是需要遍历稀疏数组的次数(遍历从稀疏数组第二行开始),然后即可还原初始的二维数组。代码如下:
public static int[][] SparseToCommomArray(int [][]sparseArray) {
//初始化数组
int[][] commonArray = new int[sparseArray[0][0]][sparseArray[0][1]];
//将稀疏数组中存储的数据取出并在找到对应的位置
for(int i=0;i<sparseArray[0][2];i++) {
commonArray[sparseArray[i+1][0]][sparseArray[i+1][1]]=sparseArray[i+1][2];
}
//输出转化后的二维数组
for(int i=0;i<commonArray.length;i++) {
for(int j=0;j<commonArray[i].length;j++) {
System.out.print(commonArray[i][j]+" ");
}
System.out.println();
}
return commonArray;
}
最后附上整个完整的代码:
/**
* 稀疏数组
* @author lhq
*
*/
public class SparseArray {
public static void main(String[] args) {
//有效数据个数
int sum=0;
//初始化数组
int array[][]= new int[11][11];
//有效数据
array[1][2]=1;
array[2][4]=2;
array[10][2]=3;
array[8][2]=4;
//统计有效数据个数
System.out.println("初始二维数组为:");
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[i].length;j++) {
System.out.print(array[i][j]+" ");
if(array[i][j]!=0)
sum++;
}
System.out.println();
}
//定义稀疏数组
int sparseArray[][]=new int[sum+1][3];
//记录行数
sparseArray[0][0] = array.length;
//记录列数
sparseArray[0][1] = array[0].length;
//记录有效数据个数
sparseArray[0][2] = sum;
//标识第几个
int count=1;
//记录对应数据
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[i].length;j++)
if(array[i][j]!=0) {
sparseArray[count][0]=i;
sparseArray[count][1]=j;
sparseArray[count][2]=array[i][j];
count++;
}
}
System.out.println("进行压缩存储之后的稀疏数组为:");
//输出稀疏数组
for(int i=0;i<sparseArray.length;i++) {
for(int j=0;j<sparseArray[i].length;j++)
System.out.print(sparseArray[i][j]+" ");
System.out.println();
}
System.out.println("将稀疏数组转化为初始二维数组为:");
SparseToCommomArray(sparseArray);
}
public static int[][] SparseToCommomArray(int [][]sparseArray) {
//初始化数组
int[][] commonArray = new int[sparseArray[0][0]][sparseArray[0][1]];
//将稀疏数组中存储的数据取出并在找到对应的位置
for(int i=0;i<sparseArray[0][2];i++) {
commonArray[sparseArray[i+1][0]][sparseArray[i+1][1]]=sparseArray[i+1][2];
}
//输出转化后的二维数组
for(int i=0;i<commonArray.length;i++) {
for(int j=0;j<commonArray[i].length;j++) {
System.out.print(commonArray[i][j]+" ");
}
System.out.println();
}
return commonArray;
}
}