Java数据结构之稀疏数组的实现与应用

作者:兴趣使然黄小黄 时间:2023-12-04 22:46:41 

1.稀疏数组引入

1.1 使用场景

笔者在课程设计中曾写过一个扫雷小游戏,为了便于讲解,我们来做个简化(实际比这个复杂),只考虑当前位置有雷与无雷两种状况:雷用1表示,非雷用0表示。则将当前状态用二维数组表示如下:

Java数据结构之稀疏数组的实现与应用

在右侧的二维数组中,很多都是0,即记录了很多没有意义的数据,因此,我们考虑使用稀疏数组进行存储结构的优化。

1.2 稀疏数组简介

当一个数组中的大部分元素都是0(或者为相同的某一值),可以考虑使用稀疏数组来优化保存。

而稀疏数组的基本处理方式为:

记录数组有几行几列,有几个有效值;

把有效值的元素的行、列及值记录在一个小规模的数组中,从而缩小程序的规模。

例如上述的二维数组用稀疏数组表示,可以创建一个n*3列的稀疏数组。其中,n为有效值个数加1,第一行用于存储二维数组的行数、列数及有效值的个数,便于恢复二维数组时使用。

而从第二行开始后的每一行,都记录某个有效值的所在行、列索引与值。

上述二维数组用稀疏数组表示如下:

稀疏数组的第n行rowcolval
010108
1041
2081
3151
4171
5481
6551
7721
8871

以索引0那行,10 10 8为例:表示原二维数组有10行10列,共有8个有效值。

以索引1那行,0 4 1为例:即第一个有效值在原数组的第0行第4列(索引为0和4),值为1,以此类推…

2.稀疏数组的实现

2.1 案例概述

1.使用稀疏数组来保存前面1.1样例中的二维数组(见下图);

2.可以由稀疏数组恢复成二维数组。

Java数据结构之稀疏数组的实现与应用

2.2 思路分析

Java数据结构之稀疏数组的实现与应用

二维数组转稀疏数组:

遍历原始的二维数组,得到有效数据的个数 amount;

根据 amount 可以创建稀疏数组 sparseArray[amount+1][3];

将二维数组中的有效值存入稀疏数组中。

稀疏数组恢复二维数组:

先读取稀疏数组的第一行,根据第一行的数据,创建原始二维数组;

读取第二行及以后行的数据,按照每行的行、列、值恢复有效值,录入二维数组中。

2.3 代码实现

根据如上思路,逐步实现稀疏数组,详情可见代码注释

参考代码:

/**
* @author 兴趣使然黄小黄
* @version 1.0
* 二维数组转稀疏数组、稀疏数组还原二维数组的实现
*/
public class SparseArray {

public static void main(String[] args) {
       //先创建原始二维数组
       int[][] originalArray = new int[10][10];
       originalArray[0][4] = 1;
       originalArray[0][8] = 1;
       originalArray[1][5] = 1;
       originalArray[1][7] = 1;
       originalArray[4][8] = 1;
       originalArray[5][5] = 1;
       originalArray[7][2] = 1;
       originalArray[8][7] = 1;
       //输出原始的二维数组
       System.out.println("原始的二维数组:");
       for (int[] row: originalArray) {
           for (int data : row) {
               System.out.printf("%d\t", data);
           }
           System.out.println();
       }

//将二维数组转成稀疏数组
       //1.遍历二维数组,得到非0的有效数据的个数
       int amount = 0;
       for (int i = 0; i < originalArray.length; i++) {
           for (int j = 0; j < originalArray[i].length; j++) {
               if (originalArray[i][j] != 0){
                   amount++;
               }
           }
       }
       System.out.println("amount = " + amount);
       //2.创建对应的稀疏数组 sparseArray[amount+1][3], 并初始化稀疏数组第一行的数据
       //第一行第一列: 原数组的行数   第一行第二列: 原数组的列数  第一行第三列: 原数组的有效数据个数
       int[][] sparseArray = new int[amount + 1][3];
       sparseArray[0][0] = 10;
       sparseArray[0][1] = 10;
       sparseArray[0][2] = amount;
       //3.遍历二维数组,将非0值存储进稀疏数组
       int count = 0; //用于记录是第几个非零数据
       for (int i = 0; i < originalArray.length; i++) {
           for (int j = 0; j < originalArray[i].length; j++) {
               if (originalArray[i][j] != 0){
                   count++;
                   sparseArray[count][0] = i; //记录所在行
                   sparseArray[count][1] = j; //记录所在列
                   sparseArray[count][2] = originalArray[i][j]; //记录值
               }
           }
       }
       //输出稀疏数组
       System.out.println("稀疏数组:");
       for (int i = 0; i < sparseArray.length; i++) {
               System.out.printf("%d\t%d\t%d\n", sparseArray[i][0], sparseArray[i][1], sparseArray[i][2]);
       }

//将稀疏数组恢复成为二维数组
       //1.根据稀疏数组的第一行初始化二维数组
       int[][] recoveredArray = new int[sparseArray[0][0]][sparseArray[0][1]];
       //2.读取稀疏数组的后面行数据,赋值给原始二维数组
       for (int i = 1; i < sparseArray.length; i++) {
           recoveredArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
       }
       //输出二维数组
       System.out.println("恢复后的二维数组:");
       for (int[] row: recoveredArray) {
           for (int data : row) {
               System.out.printf("%d\t", data);
           }
           System.out.println();
       }
   }
}

运行结果:

原始的二维数组:
0    0    0    0    1    0    0    0    1    0    
0    0    0    0    0    1    0    1    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    1    0    
0    0    0    0    0    1    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    1    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    1    0    0    
0    0    0    0    0    0    0    0    0    0    
amount = 8
稀疏数组:
10    10    8
0    4    1
0    8    1
1    5    1
1    7    1
4    8    1
5    5    1
7    2    1
8    7    1
恢复后的二维数组:
0    0    0    0    1    0    0    0    1    0    
0    0    0    0    0    1    0    1    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    1    0    
0    0    0    0    0    1    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    
0    0    1    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    1    0    0    
0    0    0    0    0    0    0    0    0    0    

比对结果如下:

Java数据结构之稀疏数组的实现与应用

经过比较,恢复后的二维数组与原二维数组保持一致!

分析可知:原二维数组需要的空间为:10 * 10 *(int),而稀疏数组只需要 9 * 3 * (int),相对节省了73(int)的空间!

来源:https://blog.csdn.net/m0_60353039/article/details/127422549

标签:Java,数据结构,稀疏,数组
0
投稿

猜你喜欢

  • Android启动页优化之实现应用秒开

    2021-05-27 23:51:32
  • 一天时间用Java写了个飞机大战游戏,朋友直呼高手

    2023-12-11 10:51:30
  • Spring Native项目实战(体验79毫秒启动springboot应用)

    2022-03-14 22:18:42
  • java根据不同的参数调用不同的实现类操作

    2021-11-08 17:05:16
  • 详解Java消息队列-Spring整合ActiveMq

    2022-12-31 04:15:41
  • JavaWeb实现注册用户名检测

    2022-07-20 05:25:46
  • android压力测试命令monkey详解

    2023-06-17 00:36:29
  • Java中关于Map四种取值方式

    2022-04-22 09:24:09
  • C# 快速高效率复制对象(表达式树)

    2023-08-15 18:07:12
  • java实现学籍管理系统

    2023-04-03 00:32:19
  • SpringMVC中的几个模型对象

    2021-09-01 19:25:44
  • 避免sql注入_动力节点Java学院整理

    2023-08-21 17:39:12
  • SpringBoot整合EasyExcel实现文件导入导出

    2021-11-07 17:14:51
  • Android Studio提示inotify大小不足的解决办法

    2022-01-06 23:48:07
  • SpringBoot自定义starter启动器的实现思路

    2023-10-09 00:55:15
  • C++编程中的函数指针初步解析

    2023-05-04 23:08:24
  • 详解LINQ入门(上篇)

    2023-10-15 05:57:30
  • Spring Boot学习入门之AOP处理请求详解

    2023-11-27 10:55:17
  • Mybatis如何实现InsertOrUpdate功能

    2022-10-11 10:26:58
  • c# String扩展 让你在PadLeft和PadRight时不再受单双字节问题困扰

    2022-09-06 12:11:54
  • asp之家 软件编程 m.aspxhome.com