最近一段时间一直在弄个小项目,但是学习过程中发现数据结构与算法这块简直是残废,于是变写项目边补一补,慢慢记录记录。
1、定义
稀疏数组是对特定二维数组的一个压缩;这个二维数组是一个包含较少特定有效数值的二维数组,如下图:
从图中我们可以看到,这个二维数组的有效数值只有两个;但是我们对这个二维数组进行持久化时,也会将这些0输入到文件中;于是我们需要将这个二维数组进行压缩。
2、压缩办法
那么将如何进行压缩呢?我们用一个新的二维数组对原来的二维数组进行保存。关于这个保存有规定。
原数值行数 | 原数值列数 | 原数组有效数值个数 |
---|---|---|
第一个数值所在行 | 数值所在列 | 数值 |
第二个数值所在行 | 数值所在列 | 数值 |
… | … | … |
第(原数组有效数值个数)数值所在行 | 数值所在列 | 数值 |
所以:
新的二维数组只有3列,有(原数组有效数值个数)行(例如,原数组有5个有效数值那么稀疏数组就是5*3),拿上图做例子:
原数组
稀疏数组
3、压缩代码实现
(1)获取原数组行、列、有效数值(给稀疏数组的第一行赋值):
//获取原数组的行
number[0][0] = shuzu.length;
//获取原数组的列
number[0][1] = shuzu[0].length;
// 定义数据总数
int sum = 0;
//遍历获取原数组值的数量
for (int i = 0; i < shuzu.length; i++) {
for (int j = 0; j < shuzu[i].length; j++) {
if(shuzu[i][j] != 0){
sum++;
}
}
}
//获取原数组有效数值个数
number[0][2] = sum;
(2)将原数组的有效数值信息放入稀疏数组中(给稀疏数值的后面行赋值)
//定义计数器
int count = 1;
// 将原数组信息放入稀疏数组中
for (int i = 0; i < shuzu.length; i++) {
for (int j = 0; j < shuzu[i].length; j++) {
if(shuzu[i][j] != 0){
number[count][0] = i;
number[count][1] = j;
number[count][2] = shuzu[i][j];
count++;
}
}
}
(3)转化方法(所有代码):
// 将数组转换成稀疏数组
public static int[][] changeXishu(int[][] shuzu){
// 定义数据总数
int sum = 0;
//遍历获取原数组值的数量
for (int i = 0; i < shuzu.length; i++) {
for (int j = 0; j < shuzu[i].length; j++) {
if(shuzu[i][j] != 0){
sum++;
}
}
}
// 创建稀疏数组
int[][] number = new int[sum+1][3];
// 稀疏数组初始化赋值
//获取原数组的行
number[0][0] = shuzu.length;
//获取原数组的列
number[0][1] = shuzu[0].length;
//获取原数组有效数值个数
number[0][2] = sum;
//定义计数器
int count = 1;
// 将原数组信息放入稀疏数组中
for (int i = 0; i < shuzu.length; i++) {
for (int j = 0; j < shuzu[i].length; j++) {
if(shuzu[i][j] != 0){
number[count][0] = i;
number[count][1] = j;
number[count][2] = shuzu[i][j];
count++;
}
}
}
return number;
}
4、持久化效果
将两个数组进行持久化输出:
// 将稀疏数组信息写入文件
FileOutputStream fileOutputStream = new FileOutputStream("use.txt");
for (int i = 0; i < ints.length; i++) {
for (int j = 0; j < ints[i].length; j++) {
fileOutputStream.write(ints[i][j]);
}
}
// 将原数组信息写入文件
FileOutputStream fileOutputStream2 = new FileOutputStream("not use.txt");
for (int i = 0; i < number.length; i++) {
for (int j = 0; j < number[i].length; j++) {
fileOutputStream2.write(number[i][j]);
}
}
效果图:
从效果图可以看出:使用要稀疏数组后,数组明显要小许多。
5、稀疏数组还原
(1)获取原数组的行列信息并创建数组:
//根据第一行的数据还原数组大小
int hang = shuzu[0][0];
int lie = shuzu[0][1];
int[][] newShuzu = new int[hang][lie];
(2)将信息进行还原:
// 第一行存储数组信息,已经初始化使用,所以这里从1开始
for (int i = 1; i < shuzu[0][2] + 1; i++) {
//获取第i个数值所在原数组的行
int newShuzuHang = shuzu[i][0];
//获取第i个数值所在原数组的列
int newShuzuLie = shuzu[i][1];
//获取第i个数值并赋值在原数组的对应行和列
newShuzu[newShuzuHang][newShuzuLie] = shuzu[i][2];
}