问题引入
在五子棋游戏或类似的游戏中,我们可以把整个棋盘想象成是一个有规律的二维数组,其值由0、1、2三个数字组成,0代表空白区域,1代表白子,2代表黑子。这种情况:即当一个数组中大部分元素为0或者为同一值时,存储该数组数据可以使用稀疏数组来对原始数组进行精简,以减少原始数组中无用数据所占的空间。
普通二维数组与稀疏数组
下图表示的是一个12×12大小的二维数组与之对应的稀疏数组表示,其中普通二维数组中有11个有效值,其余的全为无用数据0填充。稀疏数组的第一行表示有一个12行12列且11个有效数值的二维数组。第二行表示,二维数组中的第2行(从0开始)、第4列的数值为1。从第二行开始,每一行表示的都是二维数组中数值的行列位置和真实值。
代码实现生成二维数组
private int[][] generatorArray() {// 初始化二维数组 int[][] arr = new int[12][12]; // 二维数组赋值 arr[2][4] = 1; arr[2][5] = 1; arr[3][4] = 1; arr[3][5] = 1; arr[3][6] = 2; arr[3][7] = 2; arr[4][5] = 2; arr[4][6] = 1; arr[5][5] = 1; arr[5][6] = 2; arr[5][7] = 2; System.out.println("原始二维数组为:"); for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j] + "\t"); } System.out.println(); } System.out.println(); return arr;}
运行结果:
原始二维数组为:000000000000000000000000000011000000000011220000000002100000000001220000000000000000000000000000000000000000000000000000000000000000000000000000
二维数组转换成稀疏数组
private int[][] toSparseArray(int[][] originalArray) {// 获得原始数组行列、有效值初始化稀疏数组int sum = 0;for (int i = 0; i < originalArray.length; i++) { for (int j = 0; j < originalArray[i].length; j++) { if (originalArray[i][j] != 0) { sum += 1; } }}// 稀疏数组length为有效值个数+1int[][] sparseArray = new int[sum+1][3];// 行sparseArray[0][0] = originalArray.length;// 列sparseArray[0][1] = originalArray[0].length;// 有效值个数sparseArray[0][2] = sum;// 赋值int count = 0;for (int i = 0; i < originalArray.length; i++) { for (int j = 0; j < originalArray[i].length; j++) { if (originalArray[i][j] != 0) { count++; sparseArray[count][0] = i; sparseArray[count][1] = j; sparseArray[count][2] = originalArray[i][j]; } }}// 输出稀疏数组System.out.println("转换后的稀疏数组为:");for (int i = 0; i < sparseArray.length; i++) { for (int j = 0; j < sparseArray[i].length; j++) { System.out.print(sparseArray[i][j] + "\t"); } System.out.println();}System.out.println();return sparseArray;}
运行结果:
转换后的稀疏数组为:121211241251341351362372452461551562572
稀疏数组转换为二维数组
private int[][] toOriginalArray(int[][] sparseArray) { // 初始化原始数组 int[][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]]; // 从第二个值开始,因为第一个值存的是原始数组的行列、有效值个数等信息 for (int i = 1; i < sparseArray.length; i++) { // 由稀疏数组给原始数组赋值 originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2]; } System.out.println("转换后的二维数组为:"); for (int i = 0; i < originalArray.length; i++) { for (int j = 0; j < originalArray[i].length; j++) { System.out.print(originalArray[i][j] + "\t"); } System.out.println(); } return originalArray;}
实践运用
在真实开发中,一般是将稀疏数组数据在数据库或者文件中进行保存,这里我使用 fastjson2 将稀疏数组转换成 JSON 字符串之后保存到电脑本地(二维数组转稀疏数组),再从本地读取文件内容进行解析(稀疏数组转二维数组)。保存到数据库也是同理的操作。
保存到文件
/** * 将JSON字符串保存为文件 * @param jsonString 转换后的稀疏数组JSON字符串 * @param fileName 电脑本地文件 */private void toFile(String jsonString, String fileName) { File file = new File(fileName); FileWriter fileWriter = null; if (!file.exists()) { try { file.createNewFile(); fileWriter = new FileWriter(file); char[] chars = jsonString.toCharArray(); fileWriter.write(chars); fileWriter.flush(); } catch (IOException ioException) { ioException.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { throw new RuntimeException(e); } } }}
从文件读取并解析
/** * 从文件读取内容 * @param fileName * @return * @throws IOException */private String readFile(String fileName) throws IOException { File file = new File(fileName); FileReader reader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(reader); String line = null; System.out.println("文件读取内容为:"); while ((line = bufferedReader.readLine()) != null) { System.out.println(line); System.out.println(); return line; } reader.close(); bufferedReader.close(); return line;}/** * 由JSON字符串转换成原始二维数组 * @param jsonString * @return */private int[][] stringToOriginArray(String jsonString) { JSONArray objects = JSON.parseArray(jsonString); JSONArray s = (JSONArray) objects.get(0); // 初始化原始数组 int[][] originalArray = new int[(int)s.get(0)][(int)s.get(1)]; // 从第二个值开始,因为第一个值存的是原始数组的行列、有效值个数等信息 for (int i = 1; i < objects.size(); i++) { JSONArray se = (JSONArray) objects.get(i); originalArray[(int)se.get(0)][(int)se.get(1)] = (int)se.get(2); } System.out.println("JSON字符串转换为二维数组:"); for (int i = 0; i < originalArray.length; i++) { for (int j = 0; j < originalArray[i].length; j++) { System.out.print(originalArray[i][j] + "\t"); } System.out.println(); } return originalArray;}