数据结构之稀疏数组
1.稀疏SpareArray数组
场景
如何用简单的数据结构实现记录五子棋中黑子与白字的坐标,有存盘和读盘的功能呢?
或许你首先会想到使用二维数组来实现,但实际上除了要存储黑子、白子的坐标值,还要存储其他未放的棋盘坐标值。
假设我们将白子的值设置为“1”,黑子的值设置为“2”,未放的棋盘值设置为“0”。
使用二维数组记录棋盘:
分析:因为该二维数组的很多值是默认值 0, 因此记录了很多没有意义的数据。
那什么是稀疏数组呢?
稀疏数组:当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
处理方法:
-
记录数组一共有几行几列,有多少个不同的值。
-
把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模,在一定程度上节省了资源开销。
举个栗子:
2.实例应用
应用场景
-
使用稀疏数组,来保存类似前面的二维数组(棋盘、地图等等)
-
把稀疏数组存盘,并且可以从文件中恢复原来的二维数组
稀疏数组+IO文件字符流实现五子棋存储与读取
思路:
二维数组转稀疏数组
- 遍历原始的二维数组,得到有效数据的个数
sum
- 根据
sum
就可以创建稀疏数组int[][] parseArray = new int[sum + 1][3];
- 将二维数组的有效数据数据存入到稀疏数组
稀疏数组转原始的二维数组
- 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的
originArray[11][11]
- 在读取稀疏数组后几行的数据,并给原始的二维数组赋值
1.创建原始数组
//1.创建原始数组
int[][] chessArray = new int[11][11];
//给数组赋初始值
chessArray[1][2] = 1;
chessArray[2][3] = 2;
chessArray[4][5] = 2;
//初始数组遍历
for (int[] array : chessArray) {
for (int element : array) {
System.out.print(element + "\t");
}
System.out.println();
}
/*
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 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 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
*/
2.将原始数组转换为稀疏数组
//2.将原始数组转换为稀疏数组
int sum = 0;
for (int[] array : chessArray) {
for (int element : array) {
if (element != 0) {
sum++;
}
}
}
System.out.println();
//原始数组中有效数据个数
System.out.println(sum);
//创建稀疏数组
int[][] parseArray = new int[sum + 1][3];
parseArray[0][0] = 11;
parseArray[0][1] = 11;
parseArray[0][2] = sum;
int count = 0;
for (int i = 0; i < chessArray.length; i++) {
for (int j = 0; j < chessArray[i].length; j++) {
if (chessArray[i][j] != 0) {
count++;
parseArray[count][0] = i;
parseArray[count][1] = j;
parseArray[count][2] = chessArray[i][j];
}
}
}
System.out.println();
//转换后的稀疏数组
for (int[] array : parseArray) {
for (int element : array) {
System.out.print(element + "\t");
}
System.out.println();
}
/*
3
11 11 3
1 2 1
2 3 2
4 5 2
*/
3.将稀疏数组转换为原始数组
//3.将稀疏数组转换为原始数组
int[][] originArray = new int[parseArray[0][0]][parseArray[0][1]];
for (int i = 1; i < parseArray.length; i++) {
originArray[parseArray[i][0]][parseArray[i][1]] = parseArray[i][2];
}
System.out.println();
//转换后的原始数组
for (int[] array : originArray) {
for (int element : array) {
System.out.print(element + "\t");
}
System.out.println();
}
System.out.println();
}
/*
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 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 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
*/
4.将稀疏数组写入到文件中
public static void writeFile(int[][] parseArray) throws IOException {
FileWriter fileWriter = new FileWriter("D:/chess_data.txt");
PrintWriter printWriter = new PrintWriter(fileWriter);
for (int[] array : parseArray) {
StringBuilder stringBuilder = new StringBuilder();
for (int element : array) {
stringBuilder.append(element).append(" ");
}
printWriter.println(stringBuilder);
}
printWriter.close();
}
5.从文件中读取稀疏数组
public static void readFile() throws IOException {
FileReader fileReader = new FileReader("D:/chess_data.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String[] firstRow = bufferedReader.readLine().trim().split(" ");
int dataNum = Integer.parseInt(firstRow[2]);
int[][] parseArray = new int[dataNum+1][3];
parseArray[0][0] = Integer.parseInt(firstRow[0]);
parseArray[0][1] = Integer.parseInt(firstRow[1]);
parseArray[0][2] = dataNum;
int count = 0;
while (true){
count++;
String str = bufferedReader.readLine();
if (str == null) break;
String[] strArray = str.trim().split(" ");
parseArray[count][0] = Integer.parseInt(strArray[0]);
parseArray[count][1] = Integer.parseInt(strArray[1]);
parseArray[count][2] = Integer.parseInt(strArray[2]);
}
bufferedReader.close();
for (int[] array : parseArray) {
for (int element : array) {
System.out.print(element + "\t");
}
System.out.println();
}
}
/*
11 11 3
1 2 1
2 3 2
4 5 2
*/
欢迎关注微信公众号:第二范式