稀疏数组
稀疏数组(SparseArray)
当一个二维数组中大部分元素为 0 或同一个值的二维数组时,稀疏数组可对该二维数组进行压缩
保存。
压缩存储的好处
当原数组中存在大量的无效数据占用大量的存储空间时,压缩存储可以节省存储空间,以避
免资源的不必要的浪费 。
处理方法:
记录原数组共几行几列,有多少个非零值
把每个值的行和列的索引值记录在一个小规模的数组中,从而缩小程序规模
二维转稀疏的思路:
遍历原始二维数组,得到非零数值的个数 sum
根据 sum 创建稀疏数组 sparseArr = new int[sum +1][3]
说明:sum 大小的数组只能记录sum条数据,须增添一行来记录原数组大小
再次遍历原始二维数组,将每个非零数值所对应的行列索引与值,记录在稀疏数组中
稀疏转二维的思路:
读取稀疏数组第一行数组,获取原数组的大小,创建新的二维数组
遍历稀疏数组,读取每行的数据,并将数据恢复到对应的二维数组中
/* 压缩前的原始二维数组
0 1 2 3 4 5 6 7 8 9 <- 行索引
0 0 0 0 0 0 0 0 0 0 0 此时展示的是一个 二维数组 new Array[7][10]
1 0 0 1 0 0 0 0 0 0 0 该数组大部分都被同样的值进行填充
2 0 0 0 0 0 2 0 0 0 0 此时该数组对浪费了大量的存储空间
3 0 0 0 8 0 0 0 0 0 0 此等情况下 我们可以使用 稀疏数组
4 0 0 0 0 0 0 5 0 0 0 进行对该二数组的压缩
5 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0 0
^_ 列索引*/
/* 压缩后的稀疏数组
0 1 2 <- 行索引
row col val 该数组是上述二维数组的压缩形式
0 7 10 4 arr[0]中数组表示:new Array[7][10] 共有 4 个有效数值
1 1 2 1 其中第一个值得位置:在 Array[1][2] 的位置 数值为 1
2 2 5 2 其中第二个值得位置:在 Array[2][5] 的位置 数值为 2
3 3 3 8 稀疏数组用 第一个数组记录原数组的大小和有效值个数
4 4 6 5 后续数组记录原数组有效值的横纵索引和其值
^_ 列索引*/
代码:
package com.DataStructure.sparseArray;
import java.lang.reflect.Array;
public class SparseArray {
public static void main(String[] args) {
SparseArray spar = new SparseArray(); // 创建此类 用以调用类中方法
int[][] arr1 = spar.createArray(11, 11); // 获得一个 纵横都是 11大小的二维数组
arr1[1][2] = 1; // 为数组增加值
arr1[2][3] = 2;
spar.printArr(arr1); // 打印初始二维数组
int[][] sparse = spar.getSparse(arr1); // 将初始二维数组转换成稀疏数组
spar.printArr(sparse); // 打印稀疏数组
int[][] arr2 = spar.parseSparse(sparse); // 将稀疏数组转换成二维数组
spar.printArr(arr2); // 打印转换出的二维数组
}
// 创建一个二维数组并添加默认数据
public int[][] createArray(int row, int col) {
return new int[row][col]; // 传入参数 返回创建数组
}
// 将二维数组解析为稀疏数组
public int[][] getSparse(int[][] arr) { // 传入一个二维数组
int [][] spsArr = null; // 创建一个稀疏数组变量
int count = getNotZero(arr); // 得到传入数组中非零值的个数用以记录
int counter = 0; // 用以记录稀疏数组已经记录了第几个二维数组有效值
if (arr != null) { // 判空若为空则不使用 防止报错
spsArr = new int[count + 1][3]; // 创建稀疏数组 多一行要记录二维数组的大小与有效值个数
spsArr[0][0] = arr.length; // 第一行第一个数据记录二维数组的行数
spsArr[0][1] = arr[0].length; // 第一行第二个数据记录二维数组的列数
spsArr[0][2] = count; // 第一行第三个数据记录二维数组的有效值个数
for (int i = 0; i < arr.length; i++) { // 循环变量二维数组的值
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != 0) { // 查看每个非零的值将其信息记录在稀疏数组中
counter++; // 记录数据已经写入第几行 第几行数据正好与稀疏数组下标对应
spsArr[counter][0] = i; // 记录数值所在原二维数组行的下标
spsArr[counter][1] = j; // 记录数值所在原二维数组列的下标
spsArr[counter][2] = arr[i][j];// 记录原二维数组中以上行列下标所对应的值
}
}
}
}
return spsArr; // 若数组存在返回稀疏数组,不存在则返回 null
}
// 将稀疏数组解析为二维数组
public int[][] parseSparse(int[][] sparseArr){
int[][] arr = null; // 创建一个二维数组变量
if (sparseArr != null && 3 == sparseArr[0].length){
// 判空,并且判断传入数组是否为稀疏数组
arr = new int[sparseArr[0][0]][sparseArr[0][1]];
// 将稀疏数组第一行的二维数组大小值取出恢复二维数组大小
for (int i = 1; i < sparseArr.length; i++) {
// 将稀疏数组的每行有效值数据取出,稀疏数据第一行记录数组大小 所以从第二行取
arr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
// 取出行列对应的索引值,找的数组对应位置,将原值赋回
}
}
return arr; // 若稀疏数组存在返回二维数组,不存在则返回 null
}
// 获得数组中非零数据个数
public int getNotZero(int[][] arr) {
int count = -1; // 当传入数组为 null 时,有效数据个数返回 -1
if (arr != null) { // 判空
count = 0; // 当数组存在但是没有有效值时候,个数为0
for (int[] row : arr) { // 遍历数组
for (int data : row) {
if (data != 0) { // 判断数组中数值是否为有效值
count++; // 当此次数值有效,个数增长 1
}
}
}
}
return count;
}
// 打印二维数组
public void printArr(int[][] arr) { // 传入二维数组
if (arr != null){ // 判空,若为空则不调用打印 否则报错
for (int[] row : arr) { // 使用 ForEach 循环得到二维数组中的一维数组
for (int data : row) { // 使用 ForEach 循环得到一维数组中的每一个值
System.out.printf("%d\t", data); // 将值打印并在每个值后面增加一个制表符
}
System.out.println(); //每一个数组输出一行后换行进行输出下一个数组
}
} else {
System.out.println("数组不存在!"); // 若数组为空,则输出数组不存在
}
}
}
笔记博文,该博文用于私下交流,若有问题请各位大神提点。谢谢!!!