引言

数据压缩方面,我们往往可以通过稀疏数组来保存有效数据,节省存储空间。

一、稀疏数组的概念

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

它是一个十分有效的存储结构,便于节省存储空间。

它的处理方式是:

1、记录数组一共有几行几列有多少不同的值

2、把具有不同值的元素的行、列及值记录在一个小规模二维数组中(稀疏数组),从而缩存储数据的规模。

二、稀疏数组的存储结构

稀疏数组实际上是一个典型的二维数组,它描述的是一个标准二维数组的有效数据,如果标准二维数组的内容如下所示的话:

那么这个标准二维数组对应的稀疏数组的结构就如下图所示:

如上图所示。

稀疏数组有固定的三列,分别代表原始二维数组的行、列和值,但是第一行具有特殊的含义:稀疏数组的第一行存储原始数组的行数、列数和有效数据个数,这三个信息。而从第二行(也就是[1]行)开始,才是真正的原始二维数组的有效数据。

【扩展】稀疏数组可以描述二维数组,但同时,我认为它也可以描述更高维的数组,比如三维空间数组,那么相应稀疏数组结构也会有所变化。所以稀疏数组并不是只能描述一个二维数组,凡是可以只保存原始数组有效数据的都可以是稀疏数组,只不过二维数组对应的稀疏数组更有代表性。

三、五子棋盘的保存与复盘

五子棋可能没有几个人没玩过,那么在线上的五子棋游戏中,后台实际上并没有保存整个棋盘,而是利用稀疏数组保存有效数据,下面我们就看看如何通过Java 编写利用稀疏数组对五子棋局的保存与复盘吧。

3.1 五子棋盘的保存

假设在五子棋游戏中,数字1 代表黑子、2 代表白子,0 代表没有任何棋子,棋盘是一个可容纳 11 × 11 个棋子的正方形。黑子先行,双方都下了两步,形成了下面的局势:

public static void main(String[] args) {int[][] chessArr = new int[11][11];chessArr[1][2] = 1;chessArr[2][3] = 2;chessArr[1][4] = 1;chessArr[1][3] = 2;// 输出原始二维数组printArr(chessArr, "原始的二维数组······");
}

其中 printArr()是一个输出二维数组的静态工具方法:

/*** 输出二维数组数组工具方法*/
private static void printArr(int[][] arr, String msg) {System.out.println(msg);for (int[] row : arr) {for (int data : row) {System.out.printf("%d ", data);}System.out.println();}
}

那么这个11 × 11 的二维数组,根据上面介绍的稀疏数组的结构,进行保存,代码如下:

/*** 二维数组转稀疏数组* @param chessArr* @return*/
private static int[][] getSparseArr(int[][] chessArr) {// 将二维数组转为稀疏数组// 1、先遍历二维数组,得到非 0 数据的个数int sum = 0;// 二维数组的 length 取的是行数for (int i = 0; i < chessArr.length; i++) {for (int j = 0; j < chessArr[0].length; j++) {if (chessArr[i][j] != 0) {sum++;}}}
//      System.out.println("sum = " + sum);// 2. 创建对应的稀疏数组int[][] sparseArr = new int[sum + 1][3];// 给稀疏数组赋值sparseArr[0][0] = chessArr.length;sparseArr[0][1] = chessArr[0].length;sparseArr[0][2] = sum;// 将原始数组中的非 0 数据存放到稀疏数组中int sparseArrRow = 1;for (int i = 0; i < chessArr.length; i++) {for (int j = 0; j < chessArr[0].length; j++) {if (chessArr[i][j] != 0) {sparseArr[sparseArrRow][0] = i;sparseArr[sparseArrRow][1] = j;sparseArr[sparseArrRow][2] = chessArr[i][j];sparseArrRow++;}}}return sparseArr;
}

获得稀疏数组后输出:

int[][] sparseArr = getSparseArr(chessArr);
printArr(sparseArr, "输出稀疏数组······");

3.2 稀疏数组复盘五子棋

其实复盘的逻辑要更为简单,首先通过稀疏数组的第一行,初始化一个11 × 11 的二维数组,然后循环后面的行,取出每个数据放入到二维数组中去即可,代码如下:

/*** 复盘,稀疏数组转二维数组* @return*/
private static int[][] getReplayArr(int[][] sparseArr) {int[][] chessArr = new int[sparseArr[0][0]][sparseArr[0][1]];for (int i = 1; i < sparseArr.length; i++) {chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];}return chessArr;
}

通过上面的内容,我们重新复盘,并输出:

int[][] replayArr = getReplayArr(sparseArr);
printArr(replayArr, "复盘后的二维数组......");

可以看到,复盘后的棋盘与原始棋盘一模一样,这样就达到了利用稀疏数组节省存储空间的效果。

总结

稀疏数组总体来说还是比较简单的一个数据结构的利用,其中并未涉及任何算法,唯一的难点,可能就是二维数组转稀疏数组时的一些数组下标的思考和转化,不过通过画图也可以轻易地找出准确值。

数据结构与算法————稀疏数组相关推荐

  1. 数据结构与算法---稀疏数组

    数据结构与算法-稀疏数组 1.基本介绍: ​ 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 2.稀疏数组的处理方法是: ​ (1)记录数组一共有几行几列,有多少个 ...

  2. golang数据结构与算法——稀疏数组、队列和链表

    文章目录 一 稀疏数组 1.1 先看一个实际的需求 1.2 稀疏数组基本介绍 1.3 稀疏数组举例说明 1.4 把数组转换为稀疏数组实现 1.5 把稀疏数组还原为原数组 二 队列 2.1 队列的介绍 ...

  3. 数据结构与算法 - 稀疏数组(理解+代码实现案例)

    举例 稀疏数组第一行是原数据几行几列和几个有效数据的个数 下面的行是各个有效数组的行列与具体值 稀疏数组实现 代码实现 package DataStructures.sparsearray;/*** ...

  4. (二)数据结构与算法-稀疏数组

    先看一个实际的需求 分析问题: 因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据 -> 稀疏数组 稀疏sparsearray数组 基本介绍 当一个数组中大部分元素为0,或者为同一个 ...

  5. go数据结构与算法| 稀疏数组

    文章目录 背景 场景 假代码实现 真代码实现 背景 玩了几十年了.该还的还是要还.懂的人自然懂,不懂的自然不懂.如果你与我一样浪费了几十年青春,欢迎和我一起努力并交流,什么是生活. 仅仅是敲代码,不分 ...

  6. JavaScript数据结构和算法简述——数组

    为什么先讲数组 数据结构可以简单的被分为线性结构和非线性结构. 线性结构大致包括: 数组(连续存储): 链表(离散存储): 栈(线性结构常见应用,由链表或数组增删和改进功能实现): 队列(线性结构常见 ...

  7. JAVA描述算法和数据结构(01):稀疏数组和二维数组转换

    一.基本简介 1.基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵:与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵.定义非零元 ...

  8. java 二维数据结构_JAVA描述算法和数据结构(01):稀疏数组和二维数组转换

    一.基本简介 1.基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵:与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵.定义非零元 ...

  9. 数据结构与算法--有序数组中找出和为s的两个数字

    有序数组中找和为s的两个数字 题目:输入一个递增排序的数组array, 和一个数字s, 在数组中找出两个数,使得这两个数的和是s,如果有多对,输出一对即可. 最简单方案 双循环,每次获取一个数据,和数 ...

最新文章

  1. oc75--不可变字典NSDictionary
  2. 第5章:可复用性的软件构建方法 5.2面向复用的构造
  3. openpose_net随机搜索网络源代码
  4. java debug体系为什么不能debug到jdk里所有的代码
  5. 【LeetCode】414. 第三大的数
  6. 【NLP】Sentence-T5|谷歌提出文本表示新SOTA
  7. java递归api_javaAPI_IO流基础_递归使用
  8. jsp常用的onchange事件
  9. oracle 证书编号,说说Oracle的rowid
  10. XOS 源码详解3: os_s_xxxx.s 汇编代码的 LDR指令
  11. 战胜棋王后,人工智能是否可以颠覆安全?
  12. euv光刻机有什么用_有关EUV光刻机,你需要知道这些
  13. Ubuntu20.04如何卸载软件
  14. digester java_commons-digester 升级到 commons-digester3 的坑
  15. [POJ3177]Redundant Paths
  16. mt4双线macd_指标之王——MACD的精髓用法,八张图完美诠释最佳买入点,牢记不愁买卖!...
  17. 如何用计算机恢复出厂设置,告诉你电脑如何恢复出厂设置
  18. 淘宝内乱持续 QQ盛大京东“趁火打劫”
  19. JAVA实现跨平台的原理
  20. CCF 202206-4 光线追踪 python

热门文章

  1. 用于数据分析的Python – Pandas
  2. 为什么阿里全面推动 K8S 落地,咬紧牙关也要搞云原生?
  3. 面试官:HashSet是如何保证元素不重复的?
  4. Oracle数据库版本维护支持结束时间表以及数据库版本发行时间表
  5. 跨考计算机教研室,跨考教研室专家:脱离题海沉浮 做到有效做题_跨考网
  6. LeetCode——350. 两个数组的交集 II
  7. 科大奥锐实验报告霍尔效应_中科大929半导体物理专业课高分学长考研经验
  8. win7装mysql一直未响应_求助啊 WIN7下安装mysql出问题 老是说未响应~!!
  9. 英特尔显示器音频_英特尔也玩马甲?有关USB TypeC的冷知识你了解多少
  10. 域控制器安装完成没有_tcp_udp_究竟什么才叫域控制器?