数据结构与算法 之 稀疏数组

313 阅读3分钟

定义

稀疏数组:百度百科没有找到对其的定义,但是找到了稀疏矩阵的定义

稀疏矩阵:矩阵中非零元素的个数远远小于矩阵元素的总数,并且非零元素的分布没有规律,通常认为矩阵中非零元素的总数比上矩阵所有元素总数的值小于等于0.05时,则称该矩阵为稀疏矩阵(sparse matrix)

稀疏数组的意义与稀疏矩阵相差无几

应用场景

围棋数据存储

image.png

如图,棋盘由 15 X 15 的横轴和竖轴构成,一共有 225 个点组成。 如果用二维数据记录的话,1 表示黑子,2 表示白子。一个15 X 15 的数组就会有大量的无用数据,有效数据只有6个。

//创建一个普通二维数组
private static int[][] buildArray() {
    //原始数组:二维
    int[][] array = new int[15][15];
    array[6][6] = 1;
    array[6][8] = 2;
    array[7][7] = 1;
    array[8][8] = 1;
    array[8][10] = 2;
    array[9][9] = 2;
    return array;
}

这时就可以用稀疏数组来只存储有用信息。这样就只需要构建一个7行3列的二维数组,大大的减少了空间以及提高了存储效率。

image.png 用代码来实现一下

//二维数组转稀疏数组
private static int[][] arrToSparseArr(int[][] array) {
    /**
     *  转成稀疏数组
     *  1.遍历原数组获取3个值:数组中非0元素个数sum,原数组的行 rowxs 和列 linexs
     *  2.稀疏数组的大小为 行是sum+1,列为3的二维数组
     *  3.稀疏数组的第一行为原数组的 行,列,元素个数
     */
    int rowxs = array.length;
    int linexs = array[0].length;
    int sum = 0;
    //遍历原数组获取有效数据的个数
    for (int[] rows : array) {
        for (int row : rows) {
            if (row != 0) {
                sum++;
            }
        }
    }
    //构建稀疏数组
    int[][] sparseArr = new int[sum + 1][3];
    //记录稀疏数组的下标
    int index = 0;
    sparseArr[index][0] = rowxs;
    sparseArr[index][1] = linexs;
    sparseArr[index][2] = sum;
    index++;

    //遍历原数组创建稀疏数组的记录
    for (int i = 0; i < array.length; i++) {
        //获取每一行的数据
        int[] rows = array[i];
        for (int lines = 0; lines < rows.length; lines++) {
            //判断每一个数据是否 != 0
            if (array[i][lines] != 0) {
                sparseArr[index][0] = i;
                sparseArr[index][1] = lines;
                sparseArr[index][2] = rows[lines];
                index++;
            }
        }
    }
    return sparseArr;
}

打印一下原数组和稀疏数组

public static void main(String[] args) {
    int[][] array = buildArray();
    System.out.println("原数组");
    printArr(array);
    //转为稀疏数组
    int[][] sparseArr = arrToSparseArr(array);
    System.out.println("转为稀疏数组");
    printArr(sparseArr);
}

image.png

效果还是很明显的吧,哈哈哈!!!

接下来看一下存入磁盘的大小区别。

```
public static void main(String[] args) {
    //存入磁盘中
    saveToFile(array,FILENAME_ARRAY);
    saveToFile(sparseArr,FILENAME_SPARSEARRAY);
}
```

/**
 * 将稀疏数组存盘
 * @param sparseArray   数组
 * @param fileName      文件路径
 */
public static void saveToFile(int[][] sparseArray,String fileName) {
    FileWriter fileWriter = null;
    try {
        fileWriter = new FileWriter(new File(fileName));
        for (int[] array : sparseArray) {
            fileWriter.write(array[0] + array[1] +  array[2]);
            fileWriter.write("\r\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image.png

大小相差一倍多,还是比较明显的。

总结

如果存储类似围棋这种有效数据远远少于总体数据的情况,就可以考虑使用稀疏数组的方式来实现。

finally

public void isLike(){
    boolean 喜欢 = true;
    if(喜欢){
        "关注公众号:程序猿自来也 ";
        "扫他 ↓↓↓↓↓↓"
    }
}

cxyzilaiye.jpg