数据结构与算法--稀疏数组
简介
稀疏数组即原数组的一个压缩数组,在原数组中存在大量无意义的值,占据了大量的存储空间,只有部分坐标下的值才有意义。例如如下11*11的数组中就只有三个有意义的数字
0 0 0 0 0 0 0 0 0 0 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 2 0 0 0 0 0 0 0 0
0 0 0 3 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 0 0 0 0 0 0 0 0 0 0
则上方数组对应的稀疏数组如下
- 第一行存放原数组对用的总的行列数以及有意义的值的个数
- 其余行存放有意义的数对应的值以及其在稀疏数组中的下标值
11 11 3
2 1 1
3 2 2
4 3 3
稀疏数组的意义
- 原数组中存在大量无意义的数据占据了大量的内存存储空间
- 如要将原数组持久化到磁盘中将会占据大量的磁盘存储空间,也不利于IO读取文件
稀疏数组的实现
实现稀疏数组的同时并将其持久化到磁盘中和从磁盘持久化文件中还原原数组
import java.io.*;
public class SparseArray {
/**压缩数组文件存放位置*/
public static final String FILE_PATH = "C:\\compressArray.txt";
/**
* 数组压缩
* @param arr
*/
public static int[][] compressArray(int[][] arr){
//空数组直接返回
if (arr == null) {
return null;
}
//统计数组中非零的个数
int countNum = countNum(arr);
//压缩数组不存在需要压缩的数据
if (countNum == 0) {
return null;
}
//新建压缩数组
int[][] compressArray = new int[countNum + 1][3];
//存储需要压缩数据的数据量
compressArray[0][0] = arr.length;
compressArray[0][1] = arr[0].length;
compressArray[0][2] = countNum;
//稀疏数组开始存储原数组中需要压缩的数据
int rowNum = 1;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != 0) {
compressArray[rowNum][0] = i;
compressArray[rowNum][1] = j;
compressArray[rowNum][2] = arr[i][j];
rowNum++;
}
}
}
//将压缩的数组保存到磁盘中
try {
saveOnDisk(compressArray);
} catch (IOException e) {
e.printStackTrace();
}
return compressArray;
}
/**
* 统计数组中非零的个数
* @param arr
* @return
*/
private static int countNum(int[][] arr){
//空数组直接返回
if (arr == null) {
return 0;
}
int count = 0;
for (int[] num : arr) {
for (int i : num) {
if (i != 0) {
count++;
}
}
}
return count;
}
/**
* 将压缩的数组保存到磁盘中
* @param compressArray
*/
private static void saveOnDisk(int[][] compressArray) throws IOException {
File compressArrayFile = new File(FILE_PATH);
if (!compressArrayFile.exists()) {
compressArrayFile.createNewFile();
}
FileWriter fileWriter = new FileWriter(compressArrayFile);
for (int[] nums : compressArray) {
for (int num : nums) {
fileWriter.write(num + "\t");
}
fileWriter.write("\n");
}
fileWriter.flush();
fileWriter.close();
}
/**
* 根据压缩数组恢复稀疏数组
* @param arr
* @return
*/
public static int[][] recoverArray(int[][] arr){
if (arr == null) {
return null;
}
//新建稀疏数组
int[][] sparesArray = new int[arr[0][0]][arr[0][1]];
for (int i = 1; i < arr.length; i++) {
sparesArray[arr[i][0]][arr[i][1]] = arr[i][2];
}
return sparesArray;
}
/**
* 从磁盘中读取压缩数组文件
* @return
* @throws IOException
*/
private static int[][] readOnDisk() throws IOException {
FileReader fileReader = new FileReader(SparseArray.FILE_PATH);
BufferedReader reader = new BufferedReader(fileReader);
String line = null;
boolean flag = true;
int[][] compressArray = null;
int rowNum = 0;
while ( (line = reader.readLine())!=null) {
String[] split = line.split("\t");
//初始化压缩数组
if (flag) {
int row = Integer.parseInt(split[2]);
compressArray = new int[row+1][3];
flag = false;
}
//填充压缩数组
for (int i = 0; i < split.length; i++) {
compressArray[rowNum][i] = Integer.parseInt(split[i]);
}
rowNum++;
}
return compressArray;
}
public static void main(String[] args) throws IOException {
//待压缩的二维数组
int[][] arr = new int[11][11];
arr[2][1] = 1;
arr[3][2] = 2;
arr[4][3] = 3;
System.out.println("--------------------待压缩的二维数组-------------------");
for (int[] ints : arr) {
for (int i : ints) {
System.out.printf("%d\t",i);
}
System.out.println();
}
System.out.println("-------------------对应的稀疏数组并持久化到磁盘中--------------------");
int[][] sparseArray = compressArray(arr);
for (int[] nums : sparseArray) {
for (int num : nums) {
System.out.printf("%d\t",num);
}
System.out.println();
}
System.out.println("-----------------读取稀疏数组的持久化文件恢复其原数组----------------------");
sparseArray = readOnDisk();
int[][] recoverArray = recoverArray(sparseArray);
for (int[] nums : recoverArray) {
for (int num : nums) {
System.out.printf("%d\t",num);
}
System.out.println();
}
}
}