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

一、案例

五子棋程序,只有两种颜色的子,连成五个就gameover。可能一个棋盘能放下100枚棋子,但是总占用空间只有不到10个,游戏就over了。那么这样存储到本地file的话,空间是极大的浪费的。这就引出了稀疏数组。
在这里插入图片描述

二、稀疏数组应用场景

当一个数组中大部分元素都是0(或是同一个值)的时候,就可以用稀疏数组来保存此数组。

三、什么是稀疏数组

1、图解

先有个原始数组,8*7的规模,如下
在这里插入图片描述

2、分析

明显发现0值的数量远大于有效数据(这里非0值代表有效数据)。而且是个数组形式,所以稀疏数组来了!拆解成下稀疏数组有如下几点:

  • 先统计出原始数组的总行数、总列数、总有效数据数作为稀疏数组的第一行。
  • 将有效数据的行列的位置以及数值存储到稀疏数组中。

比如上面的表格换成稀疏数组的存法就如下:
在这里插入图片描述

可以发现:
稀疏数组永远都是三列。
原始数组存法的话需要87=56个元素空间
稀疏数组存法的话需要11
3=33个元素空间,效果很明显

3、代码

用代码证明上述图片,代码中有详细的关键性注释,一看就懂。

package com.chentongwei.struct.sparsearray;

/**
 * Description: 稀疏数组
 *
 * @author TongWei.Chen 2019-12-12 14:39:08
 */
public class MySparseArray3 {
    public static void main(String[] args) {
        int[][] originArray = new int[8][7];
        originArray[0][2] = 12;
        originArray[0][4] = 2;
        originArray[1][1] = 1;
        originArray[2][3] = -5;
        originArray[3][5] = 10;
        originArray[4][0] = 1;
        originArray[6][0] = 55;
        originArray[6][3] = 4;
        originArray[7][0] = 7;
        originArray[7][4] = 20;
        System.out.println("---------------------原始数组---------------------");
        // print原始数组
        print(originArray);
        System.out.println("---------------------稀疏数组---------------------");
        // 原始数组转稀疏数组
        int[][] spraseArray = originToSparse(originArray);
        print(spraseArray);
        System.out.println("---------------------原始数组---------------------");
        // 稀疏数组转原始数组
        int[][] originArray2 = sparseToOrigin(spraseArray);
        print(originArray2);
    }

    // print
    private static void print(int[][] array) {
        for (int[] arr : array) {
            for (int data : arr) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }
    }

    // 原始数组->稀疏数组
    private static int[][] originToSparse(int[][] originArray) {

        // 先找到有效元素行(个)数
        int count = 0;
        for (int i = 0; i < originArray.length; i++) {
            for (int j = 0; j < originArray[i].length; j ++) {
                if (originArray[i][j] != 0) {
                    count ++;
                }
            }
        }

        // 为什么是count + 1?因为count代表有效数据行数,但是再顶部还有一个总的行数、列数、值数
        int[][] spraseArray = new int[count + 1][3];
        // 为稀疏数组的第一行赋值
        spraseArray[0][0] = originArray.length;
        spraseArray[0][1] = originArray[0].length;
        spraseArray[0][2] = count;

        // 组装稀疏数组
        int index = 0;
        for (int i = 0; i < originArray.length; i++) {
            for (int j = 0; j < originArray[i].length; j ++) {
                if (originArray[i][j] != 0) {
                    index ++;
                    spraseArray[index][0] = i;
                    spraseArray[index][1] = j;
                    spraseArray[index][2] = originArray[i][j];
                }
            }
        }

        return spraseArray;
    }

    // 稀疏数组->原始数组
    private static int[][] sparseToOrigin(int[][] sparseArray) {
        // 先构建出原始数组的行列
        int[][] originArray = new  int[sparseArray[0][0]][sparseArray[0][1]];
        // 再往上面卯值
        for (int i = 1; i < sparseArray.length; i ++) {
            for (int j = 0; j < sparseArray[i].length; j ++) {
                originArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][j];
            }
        }
        return originArray;
    }
}

4、结果

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

【原】编程界的小学生

没有打赏我依然会坚持。

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

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

打赏作者

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

抵扣说明:

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

余额充值