一.基本介绍
稀疏数组(Sparse Array)是一种特殊的数据结构,主要用于存储那些大部分元素为零或者未使用的大型数组。在实际应用中,如果一个数组(尤其是多维数组或矩阵)的非零元素相对较少,直接存储整个数组将会非常浪费存储空间。在这种情况下,采用稀疏数组可以极大地减少存储需求,并提高处理效率。
二.特点与实现原理
-
定义: 稀疏数组是指那些大部分内容值为空(通常为0)的数组。对于多维数组而言,若非零元素的数量远少于总元素数量,并且这些非零元素分布无规律,则称该数组为稀疏数组。
-
存储方式:
- 三元组表示法:将非零元素及其坐标信息(行、列)作为记录存储,每条记录包含三个数据:(行索引, 列索引, 元素值)。
- 压缩稀疏行(CSR)或压缩稀疏列(CSC)格式:更高级的稀疏数组存储格式,通过三个数组分别存储非零元素值、对应的行索引和列开始位置索引,从而更快地访问和操作非零元素。
-
应用场景:
- 游戏编程中的地图数据存储,如棋类游戏(五子棋、围棋等),只需要存储落子的位置及其状态。
- 大规模科学计算中的稀疏矩阵运算,例如在有限元分析、网络图论等领域。
三.操作流程
1.二维数组转稀疏数组
1 遍历原始的数组,得到有效数据个数 sum
2 根据sum就可以创建稀疏数组sparseArr int[sum+1][3]
3 将二维数组的有效数据存入到稀疏数组
2.稀疏数组转二维数组
1 读取到稀疏数组的第一行,根据第一行的数据创建原始二维数组
2 读取稀疏数组后几行的数据并赋给原始的二维数组
四.代码展现
1.二维数组转稀疏数组
/*
创建原始的二维数组 11 * 11
0 表示空格 无棋子
1 表示 黑子
2 表示 白子
*/
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
chessArr1[4][5] = 2;
// 将二位数组转化为稀疏数组
// 得到几个非零数据
int sum = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if (chessArr1[i][j] != 0) {
sum++;
}
}
}
// 根据非零数据个数创建稀疏数组
int sparseArr[][] = new int[sum + 1][3];
// 稀疏数组第一行的数据
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
int count = 0;
// 给稀疏数组赋值
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if (chessArr1[i][j] != 0) {
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
2.将稀疏数组存入到内存文件中
/*
将稀疏数组保存到文件上
*/
String filePath = "/*/arr.txt";
try {
FileWriter fileWriter = new FileWriter(filePath);
for (int[] row : sparseArr) {
for (int data : row) {
fileWriter.write(Integer.toString(data) + "\t");
}
fileWriter.write("\n");
}
System.out.println("文件保存成功!");
fileWriter.close();
} catch (IOException e) {
System.out.println("文件保存失败!");
throw new RuntimeException(e);
}
3.从文件读取数据得到稀疏数组
/*
将从文件读取到的数据存入稀疏数组
*/
String line;
int sparseArr1[][] = new int[4][3];
int count1 = 0;
try {
BufferedReader reader =
new BufferedReader(new FileReader(new
File("/*/arr.txt")));
while ((line = reader.readLine()) != null) {
String[] split = line.split("\t");
sparseArr1[count1][0] = Integer.parseInt(split[0]);
sparseArr1[count1][1] = Integer.parseInt(split[1]);
sparseArr1[count1][2] = Integer.parseInt(split[2]);
count1++;
}
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
3.稀疏数组转为二维数组
// 得到稀疏数组第一行的数据创建二维数组
int chessArr2[][] = new int[sparseArr1[0][0]][sparseArr1[0][1]];
for (int i = 1; i < sparseArr1.length; i++) {
chessArr2[sparseArr1[i][0]][sparseArr1[i][1]] = sparseArr1[i][2];
}
五.结果展现
六.总结
稀疏数组是一种优化策略,它利用了数组中大量重复或无效信息的特点,通过只存储有意义的数据,大大降低了存储成本并提高了处理效率,特别适用于具有大规模但低密度数据存储和计算的场景。
将二维数组转换回稀疏数组时, 首先,需要对原始的二维数组进行逐行逐列遍历,统计其中非零元素的数量。 根据统计出的有效(非零)数据个数 count
,创建一个新的三维数组作为稀疏数组,其大小通常是 [count + 1][3]
。之所以是 count + 1
是因为稀疏数组的第一行通常用来记录原二维数组的行数、列数以及有效元素总数。遍历原二维数组时,对于每一个非零元素,将其所在的行号、列号以及对应的值记录到稀疏数组中。每条记录占用稀疏数组的一行,格式为 [row, col, value]
。
将稀疏数组转换回二维数组时,我们实际上是利用了稀疏数组中记录的非零元素的位置信息和值,重新构建出原大而稀疏的二维数组的状态。这一过程主要应用于那些存储或传输效率要求较高的场景,在完成特定操作后恢复原始数据格式以供后续处理。
以上为稀疏数组,当然我们当中穿插了IO的读写操作,这就体现了稀疏数组在围棋逻辑的业务体现。