01-稀疏数组
1、思路
我们通过五子棋的案例来说明:
五子棋棋盘大小为11×11,我们可以用二维数组来当作这个棋盘。
// 棋盘11 × 11
final int chessboardX = 11;
final int chessboardY = 11;
int[][] chessboard = new int[chessboardX][chessboardY];
// 0[空棋],1[黑棋], 2[白棋]
chessboard[1][2] = 1;
chessboard[2][3] = 2; |
我们用0代表空棋,1代表黑棋,2代表白棋。这个二维数组就长如下的样子:
五子棋游戏都有存档读档的功能,我们现在要把这个五子棋棋盘存档,直接存档的话我们发现有大量的数字0,而数字0代表的是空棋,我们有用的棋子是白棋和黑棋,所以存储空棋是没有必要的,浪费大量的磁盘空间,我们可以通过稀疏数组来解决这一问题。
稀疏数组是一个二维数组,以下图解表示上面原始二维数组的棋盘用稀疏数组如何表示:
row:记录原数组(棋盘)和棋子的行信息。
col:记录原数组(棋盘)和棋子的列信息。
val:记录原数组(棋盘)的棋子的有效个数和棋子是白棋还是黑棋。
稀疏数组的(0, 0)处的值代表原数组(棋盘)有多少行。
稀疏数组的(0, 1)处的值代表原数组(棋盘)有多少列。
稀疏数组的(0, 2)处的值代表原数组(棋盘)的有效棋子个数(非0数,因为0是空棋,有效个数为1白棋和2黑棋的总个数)。
由此可见稀疏数组的第0行记录的是有关原数组(棋盘)有多少行和多少列和多少个有效值,所以稀疏数组的第一行是必须存在的。
接下来从稀疏数组的第1行开始:
第一行记录第一个有效棋子,(1, 0)处的值代表棋子在原数组的第几行,(1, 1)处的值代表
棋子在原数组的第几列,(1, 2)处的值表示棋子是白棋还是黑棋。
第二行记录第二个有效棋子……
以此类推……
以上为稀疏数组的思路。
2、代码实现
package com.ljkj.codetest;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
/**
* 存档
*
* @author zd
*/
public class SparseArrayOutput {
public static void main(String[] args) throws Exception {
// 棋盘11 × 11
final int chessboardX = 11;
final int chessboardY = 11;
int[][] chessboard = new int[chessboardX][chessboardY];
// 0[空棋],1[黑棋], 2[白棋]
chessboard[1][2] = 1;
chessboard[2][3] = 2;
System.out.println("原数组---------------------------------");
for (int[] ints : chessboard) {
System.out.println(Arrays.toString(ints));
}
/*
row col val
0 11 11 非0有效值的个数count = 2
1 1 2 1
2 2 3 2
*/
// 有效值的个数
int count = 0;
for (int[] ints : chessboard) {
for (int anInt : ints) {
if (0 != anInt) {
count++;
}
}
}
// 创建稀疏数组 [有效值个数 + 1][固定为3(row, col, val)]
int[][] sparseArray = new int[count + 1][3];
sparseArray[0][0] = chessboardX;
sparseArray[0][1] = chessboardY;
sparseArray[0][2] = count;
// 给稀疏数组赋值
int row = 1;
for (int i = 0; i < chessboardX; i++) {
for (int j = 0; j < chessboardY; j++) {
int val = chessboard[i][j];
if (0 != val) {
sparseArray[row][0] = i;
sparseArray[row][1] = j;
sparseArray[row][2] = val;
row++;
}
}
}
System.out.println("稀疏数组---------------------------------");
for (int[] ints : sparseArray) {
System.out.println(Arrays.toString(ints));
}
// 存档
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\ZhangDong\\Desktop\\data-structure-and-algorithms\\01-稀疏数组\\data.data"));
outputStream.writeObject(sparseArray);
outputStream.flush();
outputStream.close();
}
}
package com.ljkj.codetest;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Arrays;
/**
* 读档
*
* @author zd
*/
public class SparseArrayInput {
public static void main(String[] args) throws Exception {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("C:\\Users\\ZhangDong\\Desktop\\sjjg-sf\\稀疏数组\\data.data"));
// 读取稀疏数组
int[][] sparseArray = (int[][]) inputStream.readObject();
inputStream.close();
System.out.println("稀疏数组---------------------------------");
for (int[] ints : sparseArray) {
System.out.println(Arrays.toString(ints));
}
// 棋盘大小
final int chessboardX = sparseArray[0][0];
final int chessboardY = sparseArray[0][1];
int count = sparseArray[0][2];
int[][] chessboard = new int[chessboardX][chessboardY];
for (int i = 1; i <= count; i++) {
int raw = sparseArray[i][0];
int col = sparseArray[i][1];
int val = sparseArray[i][2];
chessboard[raw][col] = val;
}
System.out.println("原数组---------------------------------");
for (int[] ints : chessboard) {
System.out.println(Arrays.toString(ints));
}
}
}
通过控制台打印可以清晰的看出稀疏数组的长度大小要比原数组小得多,当然,存档的话占用的磁盘空间也会少很多,这里我做了一个测试,分别对原数组存档和稀疏数组存档所占用空间进行记录,可以通过以下截图进行对比。
通过对比可以发现,节省了不少占用空间。
以上就是稀疏数组的思路和代码实现。