1.背景
1.1.假设让你开发一个五子棋,你会如何存储棋盘
1.2.数组保存棋盘
假设:
0-白表示空白位置(即没有走过的位置)
1-表示白棋
2-表示黑棋
如果是数组保存棋盘,你会发现很多数据都是零,如下图:
上面,我们通过二维数组的方法,将棋盘数据保存在了一个二维数组中,整个数组我们用了 16 × 16(共 256)个点来保存数据,其中有 254 个点都是空的。
实际来说,我们只需要将有价值的黑白子保存起来即可,因为只要我们知道黑白子数据,以及棋盘的大小,那么这 254 个空点是可以不用进行保存的。
把这样没有价值的数据起来,不但会浪费存储空间的大小,如果写入到磁盘中,还会增大 IO 的读写量,影响性能,这就是用普通二维数组来表示棋盘数据的不足之处。
那么,针对以上情况,我们该如何将我们的数据格式进行优化呢?于是就引出了我们接下来的稀疏数组的概念。
1.3.稀疏数组
稀疏数组本质上也是数组,只是存储数据时只存在元数据的规模和数据两部分
稀疏数组
列是固定的3列,分别为原数组的(行,列,值)
行,第一行表示数据规模,即表示原来的数组(有多少行,有多少列,有多少个值)
如下图所示:
2.普通数组与稀疏数组互转
package com.ldp.course.structure.demo02sparsearray; import com.ldp.course.common.MyArrayUtil; import org.junit.Test; import java.util.LinkedList; /** * @create 06/29 7:23 * @description <P> * 数据结构之稀疏数组 * 课件:https://www.cnblogs.com/newAndHui/p/16421898.html * </P> */ public class Test01 { /** * 二维数组保存棋盘演示 */ @Test public void test01() { // 建立一个16*16的棋盘 int[][] array = new int[16][16]; // 设置2个棋子的位置 array[8][7] = 1; array[9][8] = 2; System.out.println("显示棋盘"); MyArrayUtil.showArray(array); System.out.println("二维数组转为稀疏数组"); int[][] sparse = arrayToSparse(array); MyArrayUtil.showArray(sparse); System.out.println("稀疏数组转二维数组"); int[][] array2 = sparseToArray(sparse); MyArrayUtil.showArray(array2); } /** * 1.确定稀疏数组的行:遍历数组得到数组的值个数n,n+1作为稀疏数组的行 * 2.稀疏数组的列为固定值3 * 二维数组转为稀疏数组 * * @param array 二维数组 * @return 稀疏数组 */ public int[][] arrayToSparse(int[][] array) { // 确定数组有效值个数 int row = 0, col = 0, n = 0; // 记录二维数组每个值的行列值,格式(行,列,值) LinkedList<String> arrayStrList = new LinkedList<>(); for (int[] ints : array) { row++; col = 0; for (int anInt : ints) { col++; if (anInt != 0) { n++; // 行,列,值 String str = "" + (row - 1) + "," + (col - 1) + "," + anInt; arrayStrList.addLast(str); } } } // 第一行是 行,列,个数 String strFirst = "" + row + "," + col + "," + n; arrayStrList.addFirst(strFirst); // 创建稀疏数组对象 int[][] sparseArray = new int[n + 1][3]; for (int i = 0; i < (n + 1); i++) { String s = arrayStrList.get(i); // System.out.println(s); String[] rowStr = s.split(","); sparseArray[i][0] = Integer.valueOf(rowStr[0]); sparseArray[i][1] = Integer.valueOf(rowStr[1]); sparseArray[i][2] = Integer.valueOf(rowStr[2]); } return sparseArray; } /** * 稀疏数组转二维数组 * * @param sparseArray 稀疏数组 * @return 二维数组 */ public int[][] sparseToArray(int[][] sparseArray) { int row = sparseArray[0][0]; int col = sparseArray[0][1]; int n = sparseArray[0][2]; int[][] array = new int[row][col]; // 注意这里循环i<n+1,原因是第一行是数据规模,顺然只有2个值,但是实际是3行,如下 // [16, 16, 2] // [8, 7, 1] //[9, 8, 2] for (int i = 1; i < n + 1; i++) { int row_ = sparseArray[i][0]; int col_ = sparseArray[i][1]; int value_ = sparseArray[i][2]; array[row_][col_] = value_; } return array; } }
4.总结
在存储数组数据的时候,如果存在许多默认值的数据,可以考虑使用稀疏数组来进行存储,
这样数据相对来说就会瘦小很多,不但可以节省磁盘空间,还可以优化磁盘读写时性能。