稀疏数组的实现
思想
稀疏数组是对二维数组进行简化,假如有一个棋盘,那么对棋盘的数据进行保存就会占很多内存,为了解决这一状况,就是用稀疏数组来简化二维数组。
例如:以0为下棋点,1为黑棋,2为白棋 那么棋盘中有很多没有数据的点(即0),所以保存这样的数据用稀疏数组更合适。
稀疏数组本质也是二维数组,它将棋盘中有效的数据提取出来,再次使用的时候,将有效数据展示出来就行了
稀疏数组的第一行是个特殊行,从第二行开始,是数据保存的位置。
具体实现
举个例子吧:
//先创建一个原始的二维数组11*11
// 0->没有棋子 1->黑子 2->白子
int chessArr1[][] = new int[11][11];
//为这个棋盘存放3个棋子
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
chessArr1[3][4] = 2;
那么,第一行第一个数据保存的就是这个棋盘的行数,即
sparseArr[0][0] = 11;
第一行的第二个数据保存的就是这个棋盘的列数,即
sparseArr[0][1] = 11;
第一行的第三个数据保存的是这个棋盘的有效数据的个数,即
sparseArr[0][2] = 3;
从第二行开始,每行第一个数据保存的是有效数据的所在行,第二个数据保存的是有效数据的所在列,第三个数据保存的是有效数据的值,即
//以第二行为例
sparseArr[1][0] = 1;
sparseArr[1][1] = 2;
sparseArr[1][2] = 1;
以上就是二维数组转稀疏数组的思想了,这样一个棋盘数据就极大的简化了,例如上面那个棋盘的数据转成稀疏数组就成这样的了:
而将稀疏数组恢复成二维数组也是这样的思想,只不过和上面的步骤反着来的
第一步读取稀疏数组的第一行数据创建一个二维数组
第二步读取稀疏数组的第二行数据对二维数组中所在位置进行赋值
第三步重复第二步操作,直到有效数据填充完毕
以下就是稀疏数组转二维数组的具体实现
//根据稀疏数组的第一行创建二维数组
int chessArr2[][] = new int[sparseArr1[0][0]][sparseArr1[0][1]];
//将稀疏数组中的值写入二维数组中
for (int j = 1; j <= sparseArr1[0][2]; j++) {
chessArr2[sparseArr1[j][0]][sparseArr1[j][1]] = sparseArr1[j][2];
}
System.out.println("得到的二维数组的形式为~~");
for (int[] row : chessArr2) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
完整代码
为了更好地掌握这一知识点,我们把它转成稀疏数组,然后再保存到文件中,再从文件读出恢复成稀疏数组到转成二维数组。
package com.datestructures.sparsearray;
import java.io.*;
//稀疏数组
public class SparseArray {
public static void main(String[] args) throws IOException {
//先创建一个原始的二维数组11*11
// 0->没有棋子 1->黑子 2->白子
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
chessArr1[3][4] = 2;
//输出原始数组
System.out.println("原始的二维数组");
for (int[] row : chessArr1) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
//1.将二维数组转换成稀疏数组
//先遍历二维数组,统计有多少个非零数据
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0) {
sum++;
}
}
}
System.out.println("sum=" + sum);
//2.创建对应的稀疏数组
int sparseArr[][] = new int[sum + 1][3];
//给稀疏数组赋值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//遍历二维数组 将非0数组放到sparseArr中
int count = 0;//count 用于记录是第几个非零数据
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0) {
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
//3.保存稀疏数组到磁盘中
//地址:E:\资料\尚硅谷Java数据结构和算法\笔记代码课件资料\作业\SparseArray
//创建一个文件对象
File file = new File("E:\\资料\\尚硅谷Java数据结构和算法\\笔记代码课件资料\\作业\\SparseArray\\map.txt");
//用来创建一个文件并向文件中写数据。
FileOutputStream fos = new FileOutputStream(file);
//构建OutputStreamWriter对象,参数可以指定编码,默认为操作系统默认编码,windows上是gbk
OutputStreamWriter write = new OutputStreamWriter(fos, "UTF-8");
//输出稀疏数组的形式
System.out.println();
System.out.println("得到的稀疏数组的形式为~~");
for (int i = 0; i < sparseArr.length; i++) {
System.out.printf("%d\t%d\t%d\t\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
if (i == sparseArr.length - 1) {
//写入到缓冲区
write.append(sparseArr[i][0] + "," + sparseArr[i][1] + "," + sparseArr[i][2]);
} else {
write.append(sparseArr[i][0] + "," + sparseArr[i][1] + "," + sparseArr[i][2] + ",");
}
}
System.out.println();
System.out.println("写入文件中...");
// 关闭写入流,同时会把缓冲区内容写入文件
write.close();
// 关闭输出流,释放系统资源
fos.close();
//4.根据文件写入稀疏数组
//向文件中读取数据。
FileInputStream fip = new FileInputStream(file);
//构建InputStreamReader对象,编码与写入相同
InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
//在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,
//所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuffer sb = new StringBuffer();
//reader.ready()告诉这个流是否准备好被读取。
// 如果InputStreamReader的输入缓冲区不为空,或者字节可以从底层字节流读取,则InputStreamReader就绪(true)。
while (reader.ready()) {
//转成char加到StringBuffer对象中
sb.append((char)reader.read());
}
System.out.println(sb.toString());
// 关闭读取流
reader.close();
// 关闭输入流,释放系统资源
fip.close();
将此字符串分割为给定的字符匹配。
String[] str = sb.toString().split(",");
// 创建对应的稀疏数组
int sparseArr1[][] = new int[str.length / 3][3];
// 给稀疏数组赋值
int i = 0;
for (String s : str) {
sparseArr1[(i - (i % 3)) / 3][i % 3] = Integer.parseInt(s);
i++;
}
System.out.println("读取文件创建的稀疏数组为~~");
for (int[] row : sparseArr1) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
//5.根据稀疏数组创建二维数组
//根据稀疏数组的第一行创建二维数组
int chessArr2[][] = new int[sparseArr1[0][0]][sparseArr1[0][1]];
//将稀疏数组中的值写入二维数组中
for (int j = 1; j <= sparseArr1[0][2]; j++) {
chessArr2[sparseArr1[j][0]][sparseArr1[j][1]] = sparseArr1[j][2];
}
System.out.println("得到的二维数组的形式为~~");
for (int[] row : chessArr2) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
}
}