⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章
⭐作者主页:@逐梦苍穹
⭐所属专栏:数据结构。数据结构专栏主要是在讲解原理的基础上拿Java实现,有时候有C/C++代码。
⭐如果觉得文章写的不错,欢迎点个关注一键三连有写的不好的地方也欢迎指正,一同进步
稀疏数组是一种压缩数据的方式,它在处理大规模二维数组时,可以用较小的存储空间来表示大部分元素都为默认值或者重复值的数组。在这种情况下,使用稀疏数组可以显著减少存储空间的占用。
稀疏数组的一般形式是一个三元组 [i, j, value]
,其中 i
和 j
表示数组中某个元素的行和列,value
表示该元素的值。通常情况下,我们会用一个二维数组来表示原始数组,并将稀疏数组存储在一个一维数组中。
比如有一个原始数组是10 X 10的,其中数据不为零的索引为:[1,2],[2,3],[3,4],其余数据为0,
如下所示:
创建一个稀疏数组,首行记录原始数组的行数、列数、非零的有效值个数,从第二行开始,记录有效值的行索引、列索引、有效值,
如下:
使用稀疏数组的优点:
使用稀疏数组的缺点:
综上所述,稀疏数组适用于大部分元素都为默认值或重复值的情况,可以显著减少存储空间的占用,但同时也需要特别注意其访问速度和代码复杂性等问题。
稀疏数组主要应用于以下场景:
总的来说,稀疏数组适用于大部分元素都为默认值或重复值的情况,可以显著减少存储空间的占用,并且在某些场景下可以提高计算效率和传输速度。
二维数组 转 稀疏数组的思路:
稀疏数组转原始的二维数组的思路
下面用代码详细实现
这里重点先了解如何实现稀疏数组和稀疏数组向原始数组的转换:
①创建原始数组
②创建稀疏数组
/**
稀疏数组
*/
public static int[][] arrayToSparseArr(int[][] array) {
//1、获取有效数据,即不为零的数据
int count = 0;
for (int[] row : array) {
for (int data : row) {
if (data != 0) {
count++;
}
}
}
//创建稀疏数组
int[][] sparseArray = new int[count + 1][3];
//设置稀疏数组首行的值
//row
sparseArray[0][0] = 10;
//row_data
sparseArray[0][1] = 10;
//value
sparseArray[0][2] = count;
//遍历存入有效数据,定义一个索引值
int index = 1;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
sparseArray[index][0] = i;
sparseArray[index][1] = j;
sparseArray[index][2] = array[i][j];
index++;
}
}
}
for (int[] row : sparseArray) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
return sparseArray;
}
完整代码:
package sparseArray;
/**
* @author 逐梦苍穹
* @date 2023/4/12 23:14
*/
public class SparseArray {
public static void main(String[] args) {
//创建原始数组
int[][] array = new int[10][10];
array[1][2] = 1;
array[2][3] = 2;
array[3][4] = 3;
System.out.println("原始数组:");
for (int[] row : array) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
//稀疏数组
System.out.println("稀疏数组:");
int[][] sparseArray = arrayToSparseArr(array);
System.out.println("稀疏数组->原始数组:");
//回到原始数组
for (int[] row : sparseArrToArray(sparseArray)) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
}
public static int[][] arrayToSparseArr(int[][] array) {
//稀疏数组
//1、获取有效数据,即不为零的数据
int count = 0;
for (int[] row : array) {
for (int data : row) {
if (data != 0) {
count++;
}
}
}
//创建稀疏数组
int[][] sparseArray = new int[count + 1][3];
//设置稀疏数组首行的值
//row
sparseArray[0][0] = 10;
//row_data
sparseArray[0][1] = 10;
//value
sparseArray[0][2] = count;
//遍历存入有效数据,定义一个索引值
int index = 1;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
sparseArray[index][0] = i;
sparseArray[index][1] = j;
sparseArray[index][2] = array[i][j];
index++;
}
}
}
for (int[] row : sparseArray) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
return sparseArray;
}
public static int[][] sparseArrToArray(int[][] sparseArr) {
int[][] array = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
array[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
return array;
}
}
下面重点说IO读写:
①IO输出流,把稀疏数组输出到文件。
思路是:
②IO输入流,把文件中的稀疏数组数据输入到内存。
思路是:
结合IO流的完整代码如下:
package sparseArray;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* @author 逐梦苍穹
* @date 2023/4/13 10:00
*/
public class SparseArrayIo {
/**
* main方法中创建原始数组和调用各种静态方法
*/
public static void main(String[] args) throws Exception {
//创建原始数组
int[][] array = new int[10][10];
array[1][2] = 1;
array[2][3] = 2;
array[3][4] = 3;
System.out.println("原始数组:");
for (int[] row : array) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
//稀疏数组
System.out.println("稀疏数组:");
int[][] sparseArray = arrayToSparseArr(array);
System.out.println("稀疏数组->原始数组:");
//回到原始数组
for (int[] row : sparseArrToArray(sparseArray)) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
//稀疏数组写入文件
String filePath = "src/sparseArray/sparseArray.txt";
boolean flag = writeSparseArrayToFile(sparseArray, filePath);
//稀疏数组数据文件写入内存
if (flag) {
//从文件写入内存
System.out.println("从文件写入内存:");
writeFileToRam(filePath);
}
}
/**
* 稀疏数组
*/
public static int[][] arrayToSparseArr(int[][] array) {
//1、获取有效数据,即不为零的数据
int count = 0;
for (int[] row : array) {
for (int data : row) {
if (data != 0) {
count++;
}
}
}
//创建稀疏数组
int[][] sparseArray = new int[count + 1][3];
//设置稀疏数组首行的值
//row
sparseArray[0][0] = 10;
//row_data
sparseArray[0][1] = 10;
//value
sparseArray[0][2] = count;
//遍历存入有效数据,定义一个索引值
int index = 1;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
sparseArray[index][0] = i;
sparseArray[index][1] = j;
sparseArray[index][2] = array[i][j];
index++;
}
}
}
for (int[] row : sparseArray) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
return sparseArray;
}
/**
* 稀疏数组转原始数组
*/
public static int[][] sparseArrToArray(int[][] sparseArr) {
int[][] array = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
array[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
return array;
}
/**
* 稀疏数组写入磁盘
*/
public static boolean writeSparseArrayToFile(int[][] sparseArray, String filePath) throws Exception {
boolean flag = false;
//得到了稀疏数组,此时要把它存入磁盘
File file = new File(filePath);
if (!file.exists()) {
flag = file.createNewFile();
}
if (flag) {
try (
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8))
) {
for (int i = 0; i < sparseArray.length; i++) {
for (int j = 0; j < sparseArray[i].length; j++) {
bw.write(sparseArray[i][j] + "\t");
}
if (i == sparseArray.length - 1) {
break;
} else {
bw.write("\n");
}
}
} catch (Exception e) {
System.out.println(e);
return false;
}
return true;
} else {
return false;
}
}
/**
* 磁盘文件写入内存
*/
public static void writeFileToRam(String filePath) throws Exception {
try (
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8))
) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}