数据结构与算法系列(1)稀疏数组详解

1、 什么是稀疏数组?

稀疏数组是对多维数组进行压缩的技术。当一个数组中大部分元素为空或者为同一个值的时候,可以使用稀疏数组来保存该数组。比如在一个6×7的二维数组当中(如下图),实际只有7个有效的元素,如果不经过处理,全部存储的话,需要占42个位置。而实际只有7个有效数据,造成了不必要的存储开支。
在这里插入图片描述

使用稀疏数组就是为了解决上面问题的,稀疏数组是一个多维数组,有N行N列,其中行数是:有效元素数+1,列数是:数组维度+1
上面图示的二维数组,用稀疏数组表示如下:
在这里插入图片描述

说明:第一行第一列是:原数组的行数,第一行第二列是:原数组的列数,第一行第三列是:原数组有效元素数。

2、稀疏数组适用的场景

稀疏数组只适合于有效数据少,但是数组较大的情况。假设一个二维数组行是m列是n 有 t个有效数据,那么稀疏数组的行数就是t+1,列数是3,所以只有在
3 ( t + 1 ) < m n = > t < m n 3 − 1 3(t+1)<mn=> t<\frac {mn} {3}-1 3(t+1)<mn=>t<3mn1

时,使用稀疏数组才能有效的对数据进行压缩。对于上面6✖7的数组如果超过12个有效元素,使用稀疏数组反而会增加开销。

那么推广到多维数组,假设n维数组可以存储S个元素,数组中有t个有效元素。那么稀疏数组的行数就是t+1,列数是n+1。只有在
( t + 1 ) ( n + 1 ) < S = > t < S n + 1 − 1 (t+1)(n+1)<S=> t<\frac {S} {n+1}-1 (t+1)(n+1)<S=>t<n+1S1
对于一个3维可存放1000个元素的数组,只有当有效元素小于249时,适用稀疏数组才能起到节省空间的作用。

3、代码实现

基于java实现,二维数据转稀疏数组,稀疏数组还原为二维数组

 /**
     * 二维数据转化为稀疏数组
     * @param array
     * @return
     */
    public static int[][] toSparseArray(int[][] array){
        int sum=0;//数组有有效元素数
        for (int i=0;i<array.length;i++) {

            for (int j = 0; j < array[i].length; j++) {
                if (array[i][j] != 0) {
                    sum++;
                }
            }
        }
        //初始化一个稀疏数组,列数为原数组的有效数据+1
        int sparseArray[][]=new int[sum+1][3];
        //第一行第一列是:原数组的行数,
        // 第一行第二列是:原数组的列数,
        // 第一行第三列是:原数组有效元素数。
        sparseArray[0][0]=array.length;
        sparseArray[0][1]=array[0].length;
        sparseArray[0][2]=sum;
        //把有效数据存储到稀疏数组中
        int 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++;
                    //第N行第一列是:原数组的数据所在行,
                    // 第N行第二列是:原数组的数据所在列,
                    // 第N行第三列是:原数组的数据。
                    sparseArray[count][0]=i;
                    sparseArray[count][1]=j;
                    sparseArray[count][2]=array[i][j];
                }
            }
        }
        return sparseArray;

    }

    /**
     * 稀疏数组还原为二维数组
     * @param sparseArray
     * @return
     */
    public static int[][] sparseArrayToArray(int[][] sparseArray){
        //数组行数
        int rows=sparseArray[0][0];
        //数组列数
        int cols=sparseArray[0][1];
        //初始化二维数组
        int array[][]=new int[rows][cols];

        for (int i = 1; i < sparseArray.length; i++) {
            array[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
        }
        return array;

    }

    /**
     *测试
     * @param args
     */
    public static void main(String[] args) {
         //创建原始二位数组
        int classArray[][]=new int[11][11];
        classArray[1][1]=1;
        classArray[3][2]=2;
        System.out.println("==============原始数组================");
        for (int i=0;i<classArray.length;i++){

            for (int j=0;j<classArray[i].length;j++){
                System.out.print(classArray[i][j]);
                System.out.print(" ");
            }
            System.out.println("");
        }
        System.out.println("==============稀疏数组================");
        int[][] sparseArray = toSparseArray(classArray);
        for (int[] arr:sparseArray){
            for (int v:arr){
                System.out.print(v);
                System.out.print(" ");
            }
            System.out.println("");
        }
        System.out.println("==============稀疏还原到二维数组================");
        int[][] array = sparseArrayToArray(sparseArray);
        for (int i=0;i<array.length;i++) {

            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j]);
                System.out.print(" ");
            }
            System.out.println(" ");
        }
    }

参考:https://www.jianshu.com/p/8693b7108a62

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

warybee

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

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

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

打赏作者

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

抵扣说明:

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

余额充值