1 实际需求
1.1 需求提出
- 编写五子棋程序,由存盘退出和续上盘的功能。
- 实现思路:
- 存盘退出:
- 定义一个二维数组,默认值是0,黑子表示1,蓝子表示2,然后将二维数组通过流存储到文件中。
- 换言之:五子棋-->二维数组-->文件。
- 续上盘:
- 从文件中通过流读取二维数组,然后将1和2的渲染到五子棋盘上。
- 换言之:文件-->二维数组-->五子棋。
1.2 分析问题
- 因为二维数组由很多默认值为0,因此记录这些0很没有意义。需要通过稀疏数组来解决。
- 此时的存盘退出:
- 五子棋-->二维数组-->稀疏数组-->文件。
- 此时的续上盘:
- 文件-->稀疏数组-->二维数组-->五子棋。
2 稀疏数组
2.1 基本介绍
- 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方法是:
- ①记录数组一共几行几列,有多少个不同的值。
- ②把具有不同值的元素的行和列记录在一个小规模的数组中,从而缩小程序的规模。
2.2 稀疏数组的举例说明
- 假设原来的二维数组如下所示:
0 | 0 | 0 | 22 | 0 | 0 | 15 |
0 | 11 | 0 | 0 | 0 | 17 | 0 |
0 | 0 | 0 | -6 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 39 | 0 |
91 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 28 | 0 | 0 | 0 | 0 |
- 此时我们可以分析出,上面的二维数组是6行7列,并且有8个值。其中第一个值22的下标是0,3。第二个值15的下标是0,6。依次类推。
- 那么对应的稀疏数组就如下所示:
行 | 列 | 值 | |
0 | 6 | 7 | 8 |
1 | 0 | 3 | 22 |
2 | 0 | 6 | 15 |
3 | 1 | 1 | 11 |
4 | 1 | 5 | 17 |
5 | 2 | 3 | -6 |
6 | 3 | 5 | 39 |
7 | 4 | 0 | 91 |
8 | 5 | 2 | 28 |
3 应用实例
3.1 二维数组转稀疏数组
- 遍历原始的二维数组,得到有效数据的个数num。
- 根据sum就可以创建稀疏数组sparseArray=new int[sum+1][3]。
- 将二维数组的有效数据保存到稀疏数组中。
- 示例:
package com.sunxiaping; /** * 稀疏数组 */ public class SparseArrayDemo { public static void main(String[] args) { //创建原始数组表示一个12*12的棋盘,其中默认值0表示没有棋子 //1表示黑子 //2表示蓝子 int[][] sourceArray = new int[12][12]; sourceArray[1][2] = 1; sourceArray[2][3] = 2; //输出原始二维数组 System.out.println("--------输出原始二维数组开始---------"); printTwoDimensionArray(sourceArray); System.out.println("--------输出原始二维数组结束---------"); int[][] sparseArray = sourceArray2SparseArray(sourceArray); //输出稀疏数组 System.out.println("--------输出输出稀疏数组开始---------"); printTwoDimensionArray(sparseArray); System.out.println("--------输出输出稀疏数组结束---------"); } /** * 输出二维数组 */ public static void printTwoDimensionArray(int[][] array) { for (int[] arr : array) { for (int e : arr) { System.out.print(e + "\t"); } System.out.println(); } } /** * 原始数组转换为稀疏数组 * * @return */ public static int[][] sourceArray2SparseArray(int[][] sourceArray) { if (null == sourceArray || sourceArray.length == 0) { return null; } //定义num获取稀疏数组的有效数字的个数 int num = 0; int row = sourceArray.length; int column = sourceArray[0].length; for (int i = 0; i < sourceArray.length; i++) { for (int j = 0; j < sourceArray[i].length; j++) { if (sourceArray[i][j] != 0) { num++; } } } //定义稀疏数组 为num+1行,3列 int[][] sparseArray = new int[num + 1][3]; //稀疏数组的第一行为 原始数组的几行几列和总共几个有效值的个数 sparseArray[0] = new int[]{row, column, num}; //稀疏数组的其他行 遍历原始二维数组,将非0的有效值保存到稀疏数组中 int count = 0;//用于记录第几个非0数据 for (int i = 0; i < sourceArray.length; i++) { for (int j = 0; j < sourceArray.length; j++) { if (sourceArray[i][j] != 0) { count++; //稀疏数组的第0列就是有效值的行 sparseArray[count][0] = i; //稀疏数组的第1列就是有效值的列 sparseArray[count][1] = j; //稀疏数组的第2列就是有效值本身 sparseArray[count][2] = sourceArray[i][j]; } } } return sparseArray; } }
3.2 稀疏数组转二维数组
- 先读取稀疏数组的第一行,根据第一行数据,创建原始的二维数组,比如 sourceArray = new int[12][12]。
- 再读取稀疏数组的后几行的数据,并赋给原始的二维数组即可。
- 示例:
package com.sunxiaping; /** * 稀疏数组 */ public class SparseArrayDemo { public static void main(String[] args) { //创建原始数组表示一个12*12的棋盘,其中默认值0表示没有棋子 //1表示黑子 //2表示蓝子 int[][] sourceArray = new int[12][12]; sourceArray[1][2] = 1; sourceArray[2][3] = 2; //输出原始二维数组 System.out.println("--------输出原始二维数组开始---------"); printTwoDimensionArray(sourceArray); System.out.println("--------输出原始二维数组结束---------"); int[][] sparseArray = sourceArray2SparseArray(sourceArray); //输出稀疏数组 System.out.println("--------输出输出稀疏数组开始---------"); printTwoDimensionArray(sparseArray); System.out.println("--------输出输出稀疏数组结束---------"); sourceArray = sparseArray2SourceArray(sparseArray); //输出原始数组 System.out.println("--------输出原始二维数组开始---------"); printTwoDimensionArray(sourceArray); System.out.println("--------输出原始二维数组结束---------"); } /** * 输出二维数组 */ public static void printTwoDimensionArray(int[][] array) { for (int[] arr : array) { for (int e : arr) { System.out.print(e + "\t"); } System.out.println(); } } /** * 原始数组转换为稀疏数组 * * @return */ public static int[][] sourceArray2SparseArray(int[][] sourceArray) { if (null == sourceArray || sourceArray.length == 0) { return null; } //定义num获取稀疏数组的有效数字的个数 int num = 0; int row = sourceArray.length; int column = sourceArray[0].length; for (int i = 0; i < sourceArray.length; i++) { for (int j = 0; j < sourceArray[i].length; j++) { if (sourceArray[i][j] != 0) { num++; } } } //定义稀疏数组 为num+1行,3列 int[][] sparseArray = new int[num + 1][3]; //稀疏数组的第一行为 原始数组的几行几列和总共几个有效值的个数 sparseArray[0] = new int[]{row, column, num}; //稀疏数组的其他行 遍历原始二维数组,将非0的有效值保存到稀疏数组中 int count = 0;//用于记录第几个非0数据 for (int i = 0; i < sourceArray.length; i++) { for (int j = 0; j < sourceArray.length; j++) { if (sourceArray[i][j] != 0) { count++; //稀疏数组的第0列就是有效值的行 sparseArray[count][0] = i; //稀疏数组的第1列就是有效值的列 sparseArray[count][1] = j; //稀疏数组的第2列就是有效值本身 sparseArray[count][2] = sourceArray[i][j]; } } } return sparseArray; } /** * 稀疏数组转原始数组 * * @param sparseArray * @return */ public static int[][] sparseArray2SourceArray(int[][] sparseArray) { if (null == sparseArray || 0 == sparseArray.length) { return null; } if (sparseArray[0].length > 3) { throw new RuntimeException("不是稀疏数组"); } //创建原始数组,行是稀疏数组第一行的第一列的值,列是稀疏数组第一行的第二列的值 int[][] sourceArray = new int[sparseArray[0][0]][sparseArray[0][1]]; //读取稀疏数组后几行的值,赋值给稀疏数组即可 for (int i = 1; i < sparseArray.length; i++) { sourceArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2]; } return sourceArray; } }