一、定义
- 数组中非零元素的个数远远小于数组元素的总数,并且非零元素的分布没有规律,则称该数组为稀疏数组(sparse array)
比较基本的定义是数组中的大多数元素为零,并且可以利用零元素节约大量存储、运算和程序运行时间
二、使用场景
- 对于一个用二维数组,如果假设存储每个数组元素需要 L 个字节,那么存储整个数组需要 mnL 个字节。但是,这些存储空间的大部分存放的是 0 元素,从而造成大量的空间浪费。为了节省存储空间,可以只存储其中的非 0 元素。
- 由定义我们可以知道稀疏数组中非零元素远远小于元素的整数是,数组中很多元素我们是用不到的,为了节省内存,我们便可以进行压缩,节约空间。
- 稀疏数组可以简单的看作为是压缩,在开发中也会使用到。比如将数据序列化到磁盘上,减少数据量,在IO过程中提高效率等等。
那么如何进行压缩?
三、存储结构
既然我们要进行一个压缩,那么我们就要先了解他是如何存储的。
- 以下面为例
//创建一个 5 x 5 的数组
int[][] spareseArrays = new int[5][5];
spareseArrays[2][1] =1;
spareseArrays[3][2] =1;
//打印结果
0 0 0 0 0 row col value
0 0 0 0 0 压缩 5 5 2
0 1 0 0 0 ======》 2 1 1
0 0 1 0 0 3 2 1
0 0 0 0 0
如何压缩的呢?
- 创建三列row(行),col(列),value(值)
- 第一行代表了数组的大小为 5 x 5 以及有两个非0值
- 下面的row和col代表在数组中下标,vlaue代表值。
- 通过行、列值三点确定一个元素在数组中的坐标以及value,这样我们就可以对大量的非零数据进行抹除,达到压缩的效果
既然可以压缩那么怎么去复原呢?
四、案例
我们通过一个经典的案例分析一下
上图为一个 11 X 11 的棋盘
- 需求:编写的五子棋程序中,有存盘退出和续上盘的功能
代码实现
public class SpareseArray {
public static void main(String[] args) throws IOException {
//创建一个11*11的二维数组 表示棋盘
int[][] chessArr = new int[11][11];
//插入两枚棋子
// 1:黑棋,2:蓝棋
chessArr[1][2] = 1;
chessArr[2][3] =2;
int sum=0;
//打印查看棋盘
for (int[] array: chessArr ){
for (int a : array){
System.out.print(" "+ a);
}
System.out.println();
}
//计算数组中非0个数,也就是一共有几个棋子
for (int[] array: chessArr ){
for (int a : array){
if (a!=0){
sum++;
}
}
}
//创建稀疏数组
//稀疏数组的大小为棋子数量加一,加一行目的是记录棋盘大小,以及非棋子数量
//3列代表 row(行),col(列),value(值)
int [][] spareseArrays = new int[sum + 1][3];
//第一行数据初始化,记录棋盘大小和棋子数量
spareseArrays[0][0] =11;
spareseArrays[0][1] =11;
spareseArrays[0][2] =sum;
int count =1;
//遍历数组得到每个棋子放记录到新数组中
for (int i=0; i<chessArr.length;i++ ){
for (int a=0; a<chessArr[i].length;a++ ){
if (chessArr[i][a]!=0){
spareseArrays[count][0] =i;
spareseArrays[count][1] =a;
spareseArrays[count][2] =chessArr[i][a];
count++;
}
}
}
//查看压缩后的数据
System.out.println("压缩后-------------------------------");
for (int[] array: spareseArrays ){
for (int a : array){
System.out.print(" "+ a);
}
System.out.println();
}
//将压缩后的数据写入磁盘
BufferedWriter out = new BufferedWriter(new FileWriter("D:\\1.txt"));
for (int[] array: spareseArrays ){
for (int a : array){
out.write(a+"\t");
}
out.write("\r\n");
}
out.close();
//读取文件恢复棋盘
BufferedReader in = new BufferedReader(new FileReader("D:\\1.txt"));
String line; //一行数据
int row=0;
int c = 0;//行数
int [][] spareseArrays2 = null;
while((line = in.readLine()) != null){
String[] temp = line.split("\t");
if (c==0){
for(int j=0;j<temp.length;j++){
//读取第一行数据,初始化数组
spareseArrays2 = new int[Integer.parseInt(temp[0])][Integer.parseInt(temp[1])];
}
} else{
//棋子复原
for(int j=0;j<temp.length;j++){
spareseArrays2[Integer.parseInt(temp[0])][Integer.parseInt(temp[1])] = Integer.parseInt(temp[2]);
}
}
c++;
row++;
}
in.close();
//恢复后的棋盘
System.out.println("恢复后的稀疏数组为");
for (int[] array: spareseArrays2 ){
for (int a : array){
System.out.print(" "+ a);
}
System.out.println();
}
}
}
如有错误请指出谢谢!!