今天和你聊聊稀疏数组!

今天和你聊聊稀疏数组!

前言1:稀疏数组出现的原因!

假设我们在玩围棋,棋盘是11*11,用0表示空位,1表示黑棋,2表示蓝棋。那用普通数组储存是不是会有很多0在占用空位,使得内存增加。所以当一个数组中有很多0的时候,为节省内存稀疏数组就应运而生了。

前言2:什么是稀疏数组?

稀疏数组也是数组的一种,行数代表普通二维数组中的非零值个数,我称之为有效数,列数固定是三列。第一列是有效数的行,第二列是有效数的列,第三列就是有效数的值。用每一行来确定一个有效值对应的坐标和值。

1.例子分析

  • 假设棋局如下,如何用普通数组和稀疏数组进行描述?
    在这里插入图片描述

  • 普通二维数组和稀疏数组表示结果的比较。
    在这里插入图片描述在这里插入图片描述

    这对比还得了,吓得我赶紧去学稀疏数组了!

2. 解题过程

1. 用普通数组记录。

首先我们应该创建一个11*11的数组,然后往里面赋值,这个应该很简单。

 // 创建一个11*11的二维数组,用0表示没有棋子,用1表示黑棋,用2表示白棋
        int[][] arrys = new int[11][11];
        arrys[1][2] = 1;
        arrys[2][3] = 2;

2. 打印二维数组元素

 for (int[] arry : arrys) {//遍历行
            for (int i : arry) {//遍历列
                System.out.print(i + " ");
            }
            System.out.println();//遍历完一行之后就换行
        }
    System.out.println("==============================");//可以选择输出分割线表示美观

3. 用稀疏数组表示

  • 遍历普通数组元素的非零值个数

    //遍历有效值个数
            int sum = 0;//用于计算元素的非零值个数
            for (int i = 0; i < 11; i++) {
                for (int j = 0; j < 11; j++) {
                    if (arrys[i][j]!= 0){
                        sum ++;
                    }
                }
            }
    
  • 创建稀疏数组并给首行,即给第0行赋值

    //创建稀疏数组并给首行,即使第0行赋值
            int[][] arr = new int[sum+1][3];
            arr[0][0] = 11;
            arr[0][1] = 11;
            arr[0][2] = sum;
    
  • 给稀疏数组其他行赋值,列数是固定的。

    //遍历二维数组,将值存放到稀疏数组中
            int count = 0;
            for (int i = 0; i < arrys.length; i++) {
                for (int j = 0; j < arrys[i].length; j++) {
                    if (arrys[i][j] != 0 ){
                        count ++;
                        arr[count][0] = i;
                        arr[count][1] = j;
                        arr[count][2] = arrys[i][j];
                    }
                }
            }
    

4. 打印稀疏数组

//输出稀疏数组
        System.out.println("输出稀疏数组:");
        System.out.println("行" + "\t" + "列" + "\t" + "有效数字");
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < 3 ; j++) {
                System.out.print(arr[i][j] + "\t");
            }
            System.out.println();
        }

到这里我们其实已经把这题解出来了,但是我们能不能把数组还原回去呢?答案是:当然能!

3.还原数组

  • 读取原来数组的长和宽

    //读取稀疏数组还原原来数组的长和宽
            int[][] arry = new int[arr[0][0]][arr[0][1]];
    
  • 还原其中的值

    //还原其中的值
            for (int i = 1; i < arr.length ; i++) {
                arry[arr[i][0]][arr[i][1]] = arr[i][2];
            }
    
  • 打印数组

    //打印还原后的稀疏数组
            System.out.println("打印还原后的稀疏数组:");
            for (int[] arry1 : arry) {
                for (int i : arry1) {
                    System.out.print( i + " ");
                }
                System.out.println();
            }
            System.out.println("==============================");
    
    

完了吗?还没完,这样麻烦对不对,那我们将它们打包成方法吧

4. 整理后代码

/**
 * 二维数组和稀疏数组
 */
public class Demon3 {
    public static void main(String[] args) {
        // 创建一个11*11的二维数组,用0表示没有棋子,用1表示黑棋,用2表示白棋
        int m = 11, n = 11;//用来设置棋盘的大小
        int[][] arrys = new int[m][n];
        arrys[1][2] = 1;
        arrys[2][3] = 2;
       PrintArry(arrys);//打印二维数组
       int[][] arr =  RewordArry(m,n,arrys);//将二维数组转换成一个稀疏数组并返回,用一个数组接收
       PrintEspecialArry(arr);//打印稀疏数组
       int[][] arr1 = ReturnArry(arr);//将稀疏数组还原为一个二维数组,并用一个数组接收
        PrintArry(arr1);//打印二维数组
       PrintArry(ReturnArry(arr));//也可以直接调用打印方法接收对象

    }

    /**
     * 打印二维数组的方法
     * @param arry1
     */
    public static void PrintArry ( int[][] arry1){//传入一个二维数组
        System.out.println("二维数组如下");
        for (int[] arry : arry1) {//遍历数组的行
            for (int i : arry) {//遍历数组的列
                System.out.print(i + " ");
            }
            System.out.println();//遍历完一行后换行
        }
        System.out.println("==============================");//输出分割线让界面美观
    }

    /**
     * 转换成稀疏数组的方法
     *
     * @param m
     * @param n
     * @param arry2
     * @return
     */
    public static int[][] RewordArry ( int m, int n, int[][] arry2){
        //遍历有效值个数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (arry2[i][j] != 0) {
                    sum++;
                }
            }
        }
        //转换为稀疏数组
        int[][] arr = new int[sum + 1][3];
        arr[0][0] = m;
        arr[0][1] = n;
        arr[0][2] = sum;
        //遍历二维数组,将值存放到稀疏数组中
        int count = 0;
        for (int i = 0; i < arry2.length; i++) {
            for (int j = 0; j < arry2[i].length; j++) {
                if (arry2[i][j] != 0) {
                    count++;
                    arr[count][0] = i;
                    arr[count][1] = j;
                    arr[count][2] = arry2[i][j];
                }
            }
        }
        return arr;
    }

    /**
     * 打印稀疏数组
     * @param arry3
     */
    public static void PrintEspecialArry ( int[][] arry3){
        System.out.println("输出稀疏数组:");
        System.out.println("行" + "\t" + "列" + "\t" + "有效数字");
        for (int i = 0; i < arry3.length; i++) {
            for (int j = 0; j < 3; j++) {//稀疏数组固定长度为三
                System.out.print(arry3[i][j] + "\t");
            }
            System.out.println();
        }
        System.out.println("==============================");
    }

    /**
     * 还原数组
     * @param arry4
     * @return
     */
    public static int[][] ReturnArry ( int[][] arry4){
        //读取稀疏数组还原原来数组的长和宽
        int[][] arry = new int[arry4[0][0]][arry4[0][1]];
        //还原其中的值
        for (int i = 1; i < arry4.length; i++) {
            arry[arry4[i][0]][arry4[i][1]] = arry4[i][2];
        }
        return arry;
    }
}

全码终!

彩蛋之送你一个有趣的注释:码农必备

/***
 *                                 _ooOoo_
 *                                o8888888o
 *                                88" . "88
 *                                (| -_- |)
 *                                 O\ = /O
 *                             ____/`---'\____
 *                           .   ' \\| |// `.
 *                            / \\||| : |||// \
 *                          / _||||| -:- |||||- \
 *                            | | \\\ - /// | |
 *                          | \_| ''\---/'' | |
 *                           \ .-\__ `-` ___/-. /
 *                        ___`. .' /--.--\ `. . __
 *                     ."" '< `.___\_<|>_/___.' >'"".
 *                    | | : `- \`.;`\ _ /`;.`/ - ` : | |
 *                      \ \ `-. \_ __\ /__ _/ .-` / /
 *              ======`-.____`-.___\_____/___.-`____.-'======
 *                    `=---='
 *
 *               .............................................
 *                       佛祖保佑             永无BUG
 */

大家晚安,头发重要!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值