稀疏数组原理基础_Java语言实现

本文介绍了稀疏数组的基本概念,特别是在处理大量0或相同值的二维数组时的压缩存储优势。通过记录非零元素的行、列索引和值,将二维数组转换为更节省空间的稀疏数组。同时,给出了从稀疏数组恢复到二维数组的思路。提供了一份简单的Java代码实现。
摘要由CSDN通过智能技术生成

稀疏数组

稀疏数组(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("数组不存在!");         // 若数组为空,则输出数组不存在
        }
    }
}

笔记博文,该博文用于私下交流,若有问题请各位大神提点。谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值