Java数据结构-稀疏数组

1. 什么是稀疏数组?
  • 介绍:

    当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组

  • 稀疏数组的处理方法是:

    1. 记录数组一共有几行几列,有多少个不同的值
    2. 把具有不同值的元素的行列及值记录在一个小规模的数组(稀疏数组)中,从而缩小程序的规模
  • 作用:

    主要是用来压缩数据的,在开发中也会用到,比如将二维数组的数据存到磁盘中,数据会特别多,可能还会有些意义不大的数据。这时候,选用稀疏数组就可以很大程度上在IO过程中提高效率

2. 二维数组对应的稀疏数组
  • 转换示例:

    在这里插入图片描述

  • 转换规则:

    1. 首先看二维数组的有用信息:

      5 行 5 列,8 个有效数字

      第 1 个有效数字,第 1 行第 3 列

      第 2 个有效数字,第 1 行第 5 列

      第 3 个有效数字,第 2 行第 1 列

      第 4 个有效数字,第 2 行第 4 列

      第 5 个有效数字,第 3 行第 1 列

      第 6 个有效数字,第 4 行第 1 列

      第 7 个有效数字,第 4 行第 2 列

      第 8 个有效数字,第 5 行第 3 列

    2. 怎么创建稀疏数组?

      • 设二维数组有效数字个数为 sum

        int sum = 8

      • 定义稀疏数组,行数为:有效数字个数+1;列数为:3

        int[][] sparseArr = new int[sum+1][3];

    3. 稀疏数组赋值规律

      • 稀疏数组的3列分别表示:row(行)、col(列)和 val(值)

      • 上图稀疏数组

        第一行的 5 5 8表示:所转换的二维数组有5行5列,8个有效数字

        第二行的 0 2 3表示:第 1 个有效数字在二维数组的第 1 行,第 3 列,值为 3

        第三行的 0 4 2表示:第 2 个有效数字在二维数组的第 1 行,第 5 列,值为 2

        第四行的 1 0 1表示:第 3 个有效数字在二维数组的第 2 行,第 1 列,值为 1

        第五行的 1 3 4表示:第 4 个有效数字在二维数组的第 2 行,第 4 列,值为 4

        第六行的 2 0 2表示:第 5 个有效数字在二维数组的第 3 行,第 1 列,值为 2

        第七行的 3 0 4表示:第 6 个有效数字在二维数组的第 4 行,第 1 列,值为 4

        第八行的 3 1 5表示:第 7 个有效数字在二维数组的第 4 行,第 2 列,值为 5

        第九行的 4 2 1表示:第 8 个有效数字在二维数组的第 5 行,第 3 列,值为 1

      • 总结一下:

        稀疏数组第一行的 第一个数 = 二维数组的行数、第二个数 = 二维数组列数、第三个数 = 二维数组的有效数字个数

        稀疏数组的总行数 = (二维数组有效个数+1),总列数 = 3

        稀疏数组的第二行起,第一个数 = (该有效数字在二维数组中的行数-1)、第二个数 = (该有效数字在二维数组中的列数-1)、第三个数 = 该有效数字的值

3. 二维数组和稀疏数组的互相转换
  • 二维数组转稀疏数组思路:
    1. 遍历 原始的二维数组,得到有效数据
    2. 根据有效数据的个数,创建稀疏数组
    3. 将二维数组的有效数据存入到稀疏数组中
  • 稀疏数组转原始二维数组的思路
    1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始二维数组
    2. 再依次读取后几行的数据,并赋给 原始二维数组 即可
4. 应用实例(代码实现)
  • 实际需求:

    实现二维数组与稀疏数组的互相转换

  • 代码:

    public class SparseArr {
        public static void main(String[] args) {
            //初始二维数组
            int rowSize=11;
            int colSize=11;
            //定义一个 11*11 的棋盘(二维数组),黑棋的值为1,白旗的值为2,空白部分的值为0(默认值)
            int[][] chessBoard =  new int[rowSize][colSize];
            //棋盘的第二行第三列为黑棋(1)
            chessBoard[1][2]=1;
            //棋盘的第三行第四列为蓝棋(2)
            chessBoard[2][3]=2;
    
    
    
            System.out.println("这是原始的二维数组...");
            //增强 for 循环遍历原始的二维数组
            for (int[] rows : chessBoard) {
                for (int qi : rows) {
                    System.out.print(qi+"\t");
                }
                System.out.println();
            }
    
            //获得转换后的稀疏数组
            int[][] sparseArr = getSparse(chessBoard,rowSize,colSize);
    
            System.out.println("---------------------------------------------------------");
    
            System.out.println("这是转换后的稀疏数组...");
            for (int[] rows : sparseArr) {
                for (int qi : rows) {
                    System.out.print(qi+"\t");
                }
                System.out.println();
            }
    
            System.out.println();
            System.out.println();
            System.out.println();
            //模拟一个稀疏数组
            int[][] arr = new int[2][3];
            arr[0][0]=4;
            arr[0][1]=3;
            arr[0][2]=1;
            arr[1][0]=2;
            arr[1][1]=1;
            arr[1][2]=7;
            System.out.println("这是原始的稀疏数组...");
            for (int[] rows : arr) {
                for (int qi : rows) {
                    System.out.print(qi+"\t");
                }
                System.out.println();
            }
    
            System.out.println("---------------------------------------------------------");
    
            //获得转换后的二维数组
            int[][] doubleArr= getDouble(arr);
    
            System.out.println("这是转换后的二维数组...");
            for (int[] rows : doubleArr) {
                for (int qi : rows) {
                    System.out.print(qi+"\t");
                }
                System.out.println();
            }
    
        }
    
        /**
         * 将稀疏数组转换为二维数组
         * @param arr 稀疏数组
         * @return 返回转换后的二维数组
         */
        private static int[][] getDouble(int[][] arr) {
            //获得二维数组的行、列
            int rowSize=arr[0][0];
            int colSize=arr[0][1];
            int[][] doubleArr = new int[rowSize][colSize];
            //给二维数组赋值
            for (int i = 1; i < arr.length; i++) {
                int row = arr[i][0];
                int col = arr[i][1];
                int value = arr[i][2];
                doubleArr[row][col]=value;
            }
            return doubleArr;
        }
    
        /**
         * 将二维数组转换为稀疏数组
         * @param chessBoard 原始二维数组
         * @param rowSize 原始二维数组的行数
         * @param colSize 原始二维数组的列数
         * @return 返回转换后的稀疏数组
         */
        private static int[][] getSparse(int[][] chessBoard,int rowSize,int colSize) {
            //获得二维数组的有效数字个数
            int sum = getSum(chessBoard);
            //创建稀疏数组
            int[][] sparseArr = new int[sum+1][3];
            //给稀疏数组第一行赋值
            sparseArr[0][0]=rowSize;
            sparseArr[0][1]=colSize;
            sparseArr[0][2]=sum;
            //count 用于记录二维数组的有效数字,是有效数字,则 count++,也便于给稀疏数组赋值
            int count = 0;
            //遍历二维数组,将非0的值存到稀疏数组中
            for (int i = 0; i < chessBoard.length; i++) {
                for (int j = chessBoard[i].length - 1; j >= 0; j--) {
                    if(chessBoard[i][j]>0){
                        //稀疏数组的赋值
                        sparseArr[++count][0]=i;
                        sparseArr[count][1]=j;
                        sparseArr[count][2]=chessBoard[i][j];
                    }
                }
            }
            return sparseArr;
        }
    
        /**
         * 获得二维数组的有效数字个数
         * @param chessBoard 二维数组
         * @return 返回有效数字个数
         */
        private static int getSum(int[][] chessBoard) {
            int sum = 0;
            for (int[] rows : chessBoard) {
                for (int qi : rows) {
                    if(qi>0)
                        sum++;
                }
            }
            return sum;
        }
    }
  • 运行结果: 在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值