1.稀疏数组

1.概念

我们来观察以下这张表,假设这是一个二维数组

00000000000000
01000000000000
00000000000000
00000010000000
00000000000000
00050000000000
00000020000000
00000000000000
00000000000010
00000100000000

可以看到在这个二维数组中,数组的大小为10*14,我们只存储了部分数据,有大量的空间处于空闲状态,这就造成了一定的空间浪费。

那有没有一种能够能达到和这种存储结构不变又节省空间的方式呢?

我们可以通过稀疏数组来实现:

我们将下表也看做一个二维数组,这个二维数组有3列

  • 第一列是存数据的行数的索引;
  • 第二列存数据的列数的索引;
  • 第三列存数据的值;

而在这张表的第一行中,每一列分别存储的是表的行高,和表的列宽,以及表中数据的个数

rowcowval
10146
111
361
535
662
8121
951

通过这样一张表,我们就记录下了原始表中所有数据的位置、个数,以及原数组的大小,我们可以通过这个数组达到与上面原数组一样的存储一样多效果,而且这个数组的大小为37,相比加大数组的1014的大小节省了大量的空间,这样的数组我们就称其为稀疏数组

2.代码实现

了解了稀疏数组的概念之后,我们要试着实现这个稀疏数组。

原数组转稀疏数组思路:
	1.遍历原始的数组,获取有效数据的个数sum;
	2.根据sum就可以确定稀疏数组的行数,即int sparsearray[sum+1][3];
	3.将二维数组的有效数据的信息存入到稀疏数组
稀疏数组转原数组思路:
	1.先读取稀疏数组第一行的数据,获取原数组的大小;
	2.在逐行读取稀疏数组,获取行列数据,将值存储到对应的原数组中;

根据分析的思路,我们来逐步实现:

1、首先需要创建一个原数组,并对数组进行部分赋值

//定义原数组:
int array[][] = new int[10][14];
array[1][1] = 1;
array[2][2] = 9;
array[3][6] = 1;
array[5][3] = 5;
array[6][6] = 2;
array[8][12] = 1;
array[9][5] = 1;

2、然后,我们需要遍历以下这个数组,看看数组中的有效数据的个数
(因为根据有效数据的个数,我们能确定稀疏数组的大小)

//统计数组中有效数据的个数
int sum = 0;
System.out.println("============原数组============");
for (int i = 0; i < array.length; i++) {
    for (int j = 0; j < array[i].length; j++) {
        if (array[i][j]!=0){
            sum++;
        }
        System.out.print(array[i][j]+" ");
    }
    System.out.println();
}

在这里插入图片描述

可以看到,数据已经成功存入数组。

3、确定稀疏数组的大小(稀疏数组的行数=有效数据的个数+1,列数始终为3) ,稀疏数组的第一行用来存储原数组的大小和有效数据的个数。

//创建稀疏数组
int sparsearray[][] = new int [sum+1][3];
//给稀疏数组的第一行赋值,第一行存储原始数组的大小,以及值的个数
sparsearray[0][0] = array.length;
sparsearray[0][1] = array[0].length;
sparsearray[0][2] = sum;

4、我们开始遍历原数组,将原数组中有效数据的信息(行,列,值)存储到稀疏数组中。

//记录是第几个非0数据,没记录一个数据的信息就+1
int count = 0;
//遍历原数组,将非0值存放的稀疏数组中
for (int i = 0; i < array.length; i++) {
    for (int j = 0; j < array[i].length; j++) {
        if (array[i][j]!=0){
            count ++;	//记录原数组中第几个非0数据
            sparsearray[count][0] = i;	//记录数组的行
            sparsearray[count][1] = j;	//记录数据的列
            sparsearray[count][2] = array[i][j];	//记录数据的值
        }
    }
}

5、遍历稀疏数组,查看值的存放是否正确

//输出稀疏数组的形式
System.out.println("============稀疏数组============");
 for (int i = 0; i < sparsearray.length; i++) {
     for (int j = 0; j < sparsearray[i].length; j++) {
         System.out.print(sparsearray[i][j]+"\t");
     }
     System.out.println();
 }

在这里插入图片描述

可以看到,每个有效数据的信息都存储到了稀疏数组中

6、将稀疏数组转化为原数组

//将稀疏数组再转换为原数组
int array_[][] = new int[sparsearray[0][0]][sparsearray[0][1]]; //根据稀疏数组确定原数组的大小
for (int i = 1; i < sparsearray.length; i++) {
    array_[sparsearray[i][0]][sparsearray[i][1]] = sparsearray[i][2];
}

7、输出原数组

//输出原数组
System.out.println("============稀疏数组转换后的原数组============");
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.println();
}

在这里插入图片描述

可以看到原数组也被完整的恢复。

通过这样一个例子可以看出,如果原数组特别大,但是利用率不高的时候,我们可以将其转换为稀疏数组,在这个例子中,原数组的大小为10*14,而稀疏数组的大小为8*3,两者所占的空间相差很大,而效果确一样。

但是不代表着稀疏数组适用于所有情况,我们通过例子可以得出另外一个结论,原数组中每增加一条数据,稀疏数组就需要增加一行数据来保存其信息,因此原数组每增加一个数据,稀疏数组就需要多耗费3倍原数组中新增数组所占的空间,所以当一个数组的空间利用率十分高时,我们也没有必要采用稀疏数组来存放数据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值