稀疏数组的实际运用

稀疏数组

基本介绍

在我们存储又大量重复元素值的二维数组时,如果使用一般的二维数组可能会用大量重复元素,这样就会浪费空间

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

五子棋的存储

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZM5daiV-1628307949468)(稀疏数组.assets/image-20210807095459518.png)]

这是一个15x15的棋盘,我们将用二维数组来表示它,0 表示空,1 表示黑子,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 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 1 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0

我们把它保存成这样的结构

	row	col	val
1	15	15	4
2	3	3	1
3	4	3	2
4	4	4	1
5	5	3	2

第一行 row 保存数组的行数,col 保存数组的列数,val 保存数组有效数值的个数

代码实现
二维数组存储
public class SparseArray {
    private int[][] sparseArray;	// 存储稀疏数组

    public static void main(String[] args) {
        // 创建一个原始的二维数组 15 * 15
        // 0:表示没有棋子,1 表示 黑子 2 表示白子
        int chessArr[][] = new int[15][15];
        chessArr[3][3] = 1;
        chessArr[4][3] = 2;
        chessArr[4][4] = 1;
        chessArr[5][3] = 2;
        // 打印原始数组
        for (int[] ints : chessArr) {
            System.out.println(Arrays.toString(ints));
        }
        // 创建稀疏数组
        SparseArray sparseArray = new SparseArray(chessArr);
        sparseArray.print();
        // 恢复二维数组
        int arr[][] = sparseArray.getArray();
        for (int[] ints : arr) {
            System.out.println(Arrays.toString(ints));
        }
    }

    public SparseArray(int[][] array){
        // 获得有效的数组数值
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {
                if (array[i][j] != 0){
                    count++;
                }
            }
        }
        // 创建稀疏数组
        sparseArray = new int[count+1][3];
        sparseArray[0][0] = array.length;
        sparseArray[0][1] = array[0].length;
        sparseArray[0][2] = count;
        // 遍历二维数组将非零的值存放到稀疏数组
        count = 0;
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                if (array[i][j] != 0){
                    count++;
                    sparseArray[count][0] = i;
                    sparseArray[count][1] = j;
                    sparseArray[count][2] = array[i][j];
                }
            }
        }

    }
    public void print(){
        for (int[] arr : sparseArray) {
            System.out.println(Arrays.toString(arr));
        }
    }

    // 返回稀疏数组
    public int[][] getSparseArray() {
        return sparseArray;
    }

    // 恢复二维数组
    public int[][] getArray(){
        int[][] arr = new int[sparseArray[0][0]][sparseArray[0][1]];
        for (int i = 1; i < sparseArray.length; i++) {
            arr[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        return arr;
    }
}

// 稀疏数组
[15, 15, 4]
[3, 3, 1]
[4, 3, 2]
[4, 4, 1]
[5, 3, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 2, 1, 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]
[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, 0, 0, 0, 0]
一维数组存储

如果我想用一维数组存储,该怎么修改呢

我们可以把数组转换成下面这样的形式

	col	val
1	225	4
2	48	1
3	63	2
4	64	1
5	78	2

一维数组转换成稀疏数组

public SparseArray(int[] array){
    int count = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] != 0){
            count++;
        }
    }
    sparseArray = new int[count+1][2];
    sparseArray[0][0] = array.length;
    sparseArray[0][1] = count;
    // 遍历一维数组将非零的值存放到稀疏数组
    count = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] != 0){
            count++;
            sparseArray[count][0] = i;
            sparseArray[count][1] = array[i];
        }
    }
}

稀疏数组转换成一维数组

public int[] getLinearArray(){
    int[] arr = new int[sparseArray[0][0]];
    for (int i = 1; i < sparseArray.length; i++) {
        arr[sparseArray[i][0]] = sparseArray[i][1];
    }
    return arr;
}

中国象棋的存储

存储中国象棋的棋盘是不是也能像五子棋一样呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sykbRX5s-1628307949471)(稀疏数组.assets/image-20210807105242784.png)]

稀疏数组

把中国象棋抽象成一维数组

int board[] = {
    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,39,37,35,33,32,34,36,38,40,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,41,0,0,0,0,0,42,0,0,0,0,0,
    0,0,0,43,0,44,0,45,0,46,0,47,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,27,0,28,0,29,0,30,0,31,0,0,0,0,
    0,0,0,0,25,0,0,0,0,0,26,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,23,21,19,17,16,18,20,22,24,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
};

使用上面的稀疏数组类来出来这个数组

[256, 32]
[51, 39]
[52, 37]
[53, 35]
[54, 33]
[55, 32]
[56, 34]
[57, 36]
[58, 38]
[59, 40]
[84, 41]
[90, 42]
[99, 43]
[101, 44]
[103, 45]
[105, 46]
[107, 47]
[147, 27]
[149, 28]
[151, 29]
[153, 30]
[155, 31]
[164, 25]
[170, 26]
[195, 23]
[196, 21]
[197, 19]
[198, 17]
[199, 16]
[200, 18]
[201, 20]
[202, 22]
[203, 24]

长度为 256 的一维数组变为了长度为 2 * 33 的二维数组,那么轮到哪一方的走子以及棋局回合数又该怎么记录呢?

	col	val
1	225	4
2	16	1
3	32	0
4	48	1
5	63	2
6	64	1
7	78	2

修改稀疏数组结构,使第二行记录红子回合数,第三行记录黑子的回合数,这样长度就变为了 2 * 35

FEN串

中国象棋是又专门的记录规范的,一个局面可以简单地用一行“FEN格式串”来表示

rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1

初始局面下长度为69

由于它是文本格式的(只牵涉到很有限的几个字母、数字和符号),因此网上传递棋局就非常方便,FEN格式串有很多载体,通常的做法是把它保存成后缀为“.FEN”的文件。FEN文件是ASCII码文件,可以用任何文本编辑软件来建立和修改,也可以通过象棋棋谱软件来产生。

两种存储方式的比较

通过对比可以发现

  • 稀疏数组在存储空间上基本达到最小。
  • 稀疏数组通用性比较好
  • 稀疏数组不方便更改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上行舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值