稀疏数组
实例题目:
例如,在一个棋盘游戏中,我们要保存棋盘的当前状态并持久化到硬盘,并且下次打开期盼的时候可以继续上一把未完成的棋盘。
//例如这是一个棋盘,其中1代表白子,2代表黑子
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 1 0 0 0 0 0 0 0
0 0 0 0 2 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 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 0 0
0 0 0 0 0 0 0 0 0 0 0
在这样的11*11的棋盘中,传统的方式是保存整个棋盘的状态,这里就需要用到11 * 11 的二维数组,这就会使用大量的内存空间去保存这些0,而这些0没有任何意义。
这种情况就需要稀疏数组去实现数组的压缩保存,其原理是只将那些有效的元素放进数组存储,而那些无意义的元素则不存储。
//
由上图我们可以看到,我们将原本的11 * 11的二维数组,压缩成了一个3*3的二维数组,这样就节约了大量的空间
这种稀疏数组中元素的存储,在第一行存储的是棋盘的信息
- 【0】【0】:棋盘的行数
- 【0】【1】:棋盘的列数
- 【0】【2】:棋盘中有效元素的个数
除去第一行之外,剩下的每条行都对应着棋盘中有效元素的行、列、和元素的值
代码实现
/**
* 稀疏数组:
* 实现棋盘的保存和重开
*/
public class SparseArray {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//创建一个11*11的棋盘
//初始数组1
int[][] chessArr1 = new int[11][11];
//白子为1,黑子为2
chessArr1[2][3] = 1;
chessArr1[3][4] = 2;
chessArr1[7][6] = 1;
//遍历棋盘,保存有效的元素个数
int sum = 0;
System.out.println("初始数组:");
for (int[] rows : chessArr1) {
for (int item : rows) {
System.out.printf("%d\t", item);
if (item != 0) sum++;
}
System.out.println();
}
//创建稀疏数组
System.out.println("稀疏数组:");
int[][] sparseArr = new int[sum + 1][3];
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//遍历原数组,获取原数组中有效元素的索引
int account = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
//如果是有效元素,则存入稀疏数组中
if (chessArr1[i][j] != 0) {
account++;
sparseArr[account][0] = i;
sparseArr[account][1] = j;
sparseArr[account][2] = chessArr1[i][j];
}
}
}
//最后的结果数组
System.out.println("稀疏数组的结果:");
for (int[] rows : sparseArr) {
for (int item : rows) {
System.out.printf("%d\t", item);
}
System.out.println();
}
//作业:将稀疏数组本地保存
//对象的序列化
FileOutputStream fos = new FileOutputStream("map.data");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(sparseArr);
os.flush();
//将本地的稀疏数组取出
//对象的反序列化
FileInputStream fis = new FileInputStream("map.data");
ObjectInputStream is = new ObjectInputStream(fis);
//继续棋局
sparseArr = (int[][]) is.readObject();
//解析稀疏数组
//创建一个新的空白数组
int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
//根据稀疏数组中的元素给新数组赋值
for (int i = 1; i < sparseArr.length; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
//打印新数组
System.out.println("新数组:");
for (int[] rows : chessArr2) {
for (int item : rows) {
System.out.printf("%d\t", item);
}
System.out.println();
}
}
}
输出的结果
初始数组:
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 1 0 0 0 0 0 0 0
0 0 0 0 2 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 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 0 0
0 0 0 0 0 0 0 0 0 0 0
稀疏数组:
稀疏数组的结果:
11 11 3
2 3 1
3 4 2
7 6 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 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 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 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 0 0
0 0 0 0 0 0 0 0 0 0 0
进程已结束,退出代码0