引入
数组是一个很常见的数据存储模式,但是有时使用数组会浪费掉一部分空间;例如在5*5的五子棋中,黑子代表1,白子代表2,而空白的区域代表0;为了表示棋盘中的数据,我们可能会使用二维数组来解决这个问题,最后的结果如下
0 1 0 2 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数据的值。
例子
还是刚才那个五子棋的例子。原数组是5*5的数组,数据如下
0 1 0 2 0
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
我们用稀疏数组来表示原数组
5 5 3
0 1 1
0 3 2
1 0 1
相比与原来的数组,稀疏数组的大小变小许多:原数组有25个元素,而稀疏数组只有12个。
实现稀疏数组
下面的程序包含5个函数,分别是:打印数组,压缩原数组为稀疏数组,将稀疏数组复原成原数组,把稀疏数组存储到硬盘,从硬盘中读取稀疏数组
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class SparsArrayStudy {
public static void main(String[] args) {
System.out.printf("\t原数组\n");
int[][] array = new int[5][5];
array[0][1] = 1;
array[0][3] = 2;
array[1][0] = 1;
print(array);
System.out.printf("\t压缩后的数组\n");
int[][] SparseArray = compress(array);
print(SparseArray);
System.out.printf("\t原数组恢复\n");
array = recovery(SparseArray);
print(array);
String source = "E:\\java程序\\hello-world\\src\\DataStructure\\SparseArray.data";
System.out.println();
System.out.println("\t将稀疏数组存入硬盘");
store(SparseArray,source); //指定存储位置
System.out.println();
System.out.println("\t从硬盘中读取稀疏数组");
SparseArray = read(source);//指定读取位置
if(SparseArray!=null) {
print(SparseArray);
}
}
//原数组压缩成稀疏数组
public static int[][] compress(int[][] array){
//遍历数组
int sum =0;
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[0].length;j++) {
if(array[i][j]!=0) {
sum++;
}
}
}
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[0].length;j++) {
if(array[i][j]!=0) {
SparseArray[count][0] = i;
SparseArray[count][1] = j;
SparseArray[count][2] = array[i][j];
count++;
}
}
}
return SparseArray;
}
//打印数组
public static void print(int[][] array) {
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[0].length;j++) {
System.out.printf("%d\t",array[i][j]);
}
System.out.println();
}
}
//把稀疏数组还原成原来数组
public static int[][] recovery(int[][] SparseArray) {
//创建原来的数组
int[][] array = new int[SparseArray[0][0]][SparseArray[0][1]];
//遍历压缩后的数组
for(int i=1;i<SparseArray.length;i++) {
array[SparseArray[i][0]][SparseArray[i][1]] = SparseArray[i][2];
}
return array;
}
//将稀疏数组存储到硬盘
public static void store(int[][] SparseArray,String source){
FileOutputStream file;
try {
file = new FileOutputStream(source,false);
BufferedOutputStream buf = new BufferedOutputStream(file);
for(int i=0;i<SparseArray.length;i++) {
for(int j=0;j<SparseArray[0].length;j++) {
buf.write(Integer.valueOf(SparseArray[i][j]).byteValue());
buf.flush();
}
}
buf.close();
file.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("\t写入成功");
}
//从硬盘中读取稀疏数组
public static int[][] read(String source) {
FileInputStream file;
int[][] SparseArray = null;
try {
file = new FileInputStream(source);
BufferedInputStream buf = new BufferedInputStream(file);
int row = buf.read();
int column = buf.read();
int sum = buf.read();
SparseArray = new int[sum+1][3];
SparseArray[0][0] = row;
SparseArray[0][1] = column;
SparseArray[0][2] = sum;
for(int i=1;i<SparseArray.length;i++) {
SparseArray[i][0]=buf.read();
SparseArray[i][1]=buf.read();
SparseArray[i][2]=buf.read();
}
buf.close();
}catch(Exception e) {
System.out.println("未找到文件");
}
return SparseArray;
}
}
结果