什么是稀疏数组?稀疏数组详解
【1】背景
如下图所示,这里有一个 15 × 15 的棋盘,如果现在要让你通过编码的方式,让你将这盘棋局保存起来,你会怎么做呢?
面对行列数据的保存,我相信大多人第一时间都会想到用二维数组进行保存。
【2】普通数组保存棋盘数据
比如,我们可以将棋盘进行抽象化,用一个 15 × 15 的二维数组来表示,然后用 0 表示空点,用 1 表示白子,用 2 表示黑子,于是就可以抽象为如下模样。
于是,我们可以通过如下代码,将数据保存到二维数组中。
/*** 将棋盘数据保存为二维数组*/
public static int[][] saveChess() {// 初始化棋盘(大小为 15 * 15),int默认为0(即空点)int[][] arr = new int[15][15];// 保存白子(用1表示)arr[5][5] = 1;arr[7][5] = 1;arr[6][7] = 1;// 保存黑子(用2表示)arr[6][6] = 2;arr[7][6] = 2;arr[8][6] = 2;arr[7][7] = 2;return arr;
}
【3】普通数组的不足之处
上面,我们通过了一个最普通的方法,将棋盘数据保存在了一个二维数组中,整个数组我们用了 15 × 15(共 225)个点来保存数据,其中有 218 个点都是空的。实际来说,我们只需要将有价值的黑白子保存起来即可,因为只要我们知道黑白子数据,以及棋盘的大小,那么这 218 个空点是可以不用进行保存的。
把这样没有价值的数据起来,不但会浪费存储空间的大小,如果写入到磁盘中,还会增大 IO 的读写量,影响性能,这就是用普通二维数组来表示棋盘数据的不足之处。
那么,针对以上情况,我们该如何将我们的数据格式进行优化呢?于是就引出了我们接下来的稀疏数组的概念。
【4】稀疏数组
所谓稀疏数组,从字面上我们也可以得知,它仍然是一个数组,他的作用就是将一个对应的数组数据进行优化,比如,我们将上面的二维数组进行优化。
我们可以定义一个数组,只记录黑白子的数据,具体如下:
从这个表中,我们可以只看到有价值的数据了,如果我们再将这个表抽象为一个二维数组,那么他的大小就是 7 * 3 = 21 个点了。
这相对之前的200多个点来说,确实少了许多节点,节省了很多存储空间。
但只这样保存也是不够的,因为我们并没有保存原棋盘的大小,那么我们不妨约定增加一行,保存原来棋盘的大小(二维数组的大小),那么我们可以用如下进行表示:
这里我们约定用第1行数据来记录原二维数组的规模,第 1 个值为原数组总行数,第 2 个值为原数组列数,第 3 个值为有价值数据的总数。
这样,我们就将原数组数据,优化为了一个稀疏数组。
【4】二维数组转稀疏数组
根据上面的原理,我们就可以通过代码方式,将原来的普通二维数组,优化为一个稀疏数组了,具体编码如下:
/*** 普通数组转稀疏数组* * @param arr_普通数组* @return 稀疏数组*/
public static int[][] castSparseArray(int[][] arr) {// 原数组的总行数int row = arr.length;// 原数组的总列数int cloumn = arr[0].length;// 获取黑白子总数int sum = 0;for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {if (arr[i][j] != 0) {sum++;}}}// 创建稀疏数组(sum+1 行表示 sum 个黑白子 + 1行规模)int[][] sparseArray = new int[sum + 1][3];// 第 1 行原二维数组的行、列、棋子总数sparseArray[0][0] = row;sparseArray[0][1] = cloumn;sparseArray[0][2] = sum;// 第 2 行开始存具体数据(每行都是一个棋子数据)int sparseRow = 0;for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {if (arr[i][j] != 0) {sparseRow++;sparseArray[sparseRow][0] = i;sparseArray[sparseRow][1] = j;sparseArray[sparseRow][2] = arr[i][j];}}}return sparseArray;
}
【5】稀疏数组转二维数组
我们用稀疏数组保存数据,主要是为了节省磁盘空间,优化 IO 读写性能,但在最终复原棋盘的时候,我们还是需要将稀疏数组的数据转化为原普通二维数组数据,那么我们又将如何通过编码的方式去实现稀疏数组转二维数组呢?对应编码如下:
/*** 稀疏数组转普通数组* * @param sparseArr_稀疏数组* @return 普通二维数组*/
public static int[][] castToArray(int[][] sparseArr) {// 获取稀疏数组第 1 行(记录了原数组的总行数和总列数)int[] rowFirst = sparseArr[0];// 初始化数组(棋盘)int row = rowFirst[0];int column = rowFirst[1];int[][] arr = new int[row][column];// 初始化数据(黑白子)for (int i = 1; i < sparseArr.length; i++) {int[] sparseRow = sparseArr[i];arr[sparseRow[0]][sparseRow[1]] = sparseRow[2];}return arr;
}
这样,我们就可以将稀疏数组还原为普通数组了。
【总结】
在存储数组数据的时候,我们如果存在许多默认值的数据,不妨用稀疏数组来进行存储,这样数据相对来说就会瘦小很多,不但可以节省磁盘空间,还可以优化磁盘读写时性能。
最后附上相关的整段代码:
/*** 二维数组与稀疏数组* * @author ZhangYuanqiang* @since 2021年5月13日*/
public class SparseArrayTest {public static void main(String[] args) {// 用二维数组保存棋盘int[][] arr = saveChess();// 打印二维数组print(arr);// 将二维数组转化为稀疏数组int[][] sparseArr = castSparseArray(arr);// 打印稀疏数组print(sparseArr);// 稀疏数组转二位数组int[][] arr2 = castToArray(sparseArr);print(arr2);}/*** 打印普通数组*/public static void print(int[][] arr) {for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr[i].length; j++) {System.out.print(arr[i][j] + "\t");}System.out.println();}System.out.println("--------------------------------------");}/*** 将棋盘数据保存为二维数组*/public static int[][] saveChess() {// 初始化棋盘(大小为 15 * 15)int[][] arr = new int[15][15];// 保存白子(用1表示)arr[5][5] = 1;arr[7][5] = 1;arr[6][7] = 1;// 保存黑子(用2表示)arr[6][6] = 2;arr[7][6] = 2;arr[8][6] = 2;arr[7][7] = 2;return arr;}/*** 普通数组转稀疏数组* * @param arr_普通数组* @return 稀疏数组*/public static int[][] castSparseArray(int[][] arr) {// 原数组的总行数int row = arr.length;// 原数组的总列数int cloumn = arr[0].length;// 获取黑白子总数int sum = 0;for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {if (arr[i][j] != 0) {sum++;}}}// 创建稀疏数组(sum+1 行表示 sum 个黑白子 + 1行规模)int[][] sparseArray = new int[sum + 1][3];// 第 1 行原二维数组的行、列、棋子总数sparseArray[0][0] = row;sparseArray[0][1] = cloumn;sparseArray[0][2] = sum;// 第 2 行开始存具体数据(每行都是一个棋子数据)int sparseRow = 0;for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {if (arr[i][j] != 0) {sparseRow++;sparseArray[sparseRow][0] = i;sparseArray[sparseRow][1] = j;sparseArray[sparseRow][2] = arr[i][j];}}}return sparseArray;}/*** 稀疏数组转普通数组* * @param sparseArr_稀疏数组* @return 普通二维数组*/public static int[][] castToArray(int[][] sparseArr) {// 获取稀疏数组第 1 行(记录了原数组的总行数和总列数)int[] rowFirst = sparseArr[0];// 初始化数组(棋盘)int row = rowFirst[0];int column = rowFirst[1];int[][] arr = new int[row][column];// 初始化数据(黑白子)for (int i = 1; i < sparseArr.length; i++) {int[] sparseRow = sparseArr[i];arr[sparseRow[0]][sparseRow[1]] = sparseRow[2];}return arr;}
}
什么是稀疏数组?稀疏数组详解相关推荐
- ES5和ES6数组遍历方法详解
ES5和ES6数组遍历方法详解 在ES5中常用的10种数组遍历方法: 1.原始的for循环语句 2.Array.prototype.forEach数组对象内置方法 3.Array.prototype. ...
- 旋转排序数组系列题详解
旋转排序数组系列题详解 文章目录 旋转排序数组系列题详解 一.问题描述:旋转数组的最小数字 二.分析:二分查找 三.代码 四.问题描述:寻找旋转排序数组中的最小值 五.分析:二分搜索 六.代码 七.问 ...
- c语言char数组和short数组的区别,详解C语言中Char型指针数组与字符数组的区别
详解C语言中Char型指针数组与字符数组的区别 详解C语言中Char型指针数组与字符数组的区别 1.char 类型的指针数组:每个元素都指向一个字符串,指向可以改变 char *name[3] = { ...
- C语言 字符数组 和 字符串 详解
C语言 字符数组 和 字符串 详解 用来存放字符的数组称为字符数组,例如: char a[10]; //一维字符数组 char b[5][10]; //二维字符数组 char c[20]={'c', ...
- pythonprint字节按照16进制输出_对python以16进制打印字节数组的方法详解
对python以16进制打印字节数组的方法详解 一.问题描述 如果直接用print打印bytes的话,有时候会直接显示ascii对应的字符,看起来很蛋疼. 二.运行效果 上面一行是直接用print打印 ...
- linux jq 遍历数组,jquery 遍历数组 each 方法详解
JQuery拿取对象的方式 $('#id') :通过元素的id $('tagName') : 通过元素的标签名 $('tagName tagName') : 通过元素的标签名,eg: $('ul li ...
- java生成字符串数组_Java 生成随机字符串数组的实例详解
Java 生成随机字符串数组的实例详解 利用Collections.sort()方法对泛型为String的List 进行排序.具体要求: 1.创建完List之后,往其中添加十条随机字符串 2.每条字符 ...
- C语言数组之间赋值详解
数组之间的赋值,C语言数组之间赋值详解 (biancheng.net)
- python的对象数组_Python当中的array数组对象实例详解
计算机为数组分配一段连续的内存,从而支持对数组随机访问: 由于项的地址在编号上是连续的,数组某一项的地址可以通过将两个值相加得出,即将数组的基本地址和项的偏移地址相加. 数组的基本地址就是数组的第一项 ...
- jQuery数组处理完全详解
jQuery的数组处理.便捷.功能齐全.最近的项目中用到的比较多,深感实用,一步到位的封装了很多原生JavaScript数组不能企及的功能.最近时间紧迫,今天抽了些时间回过头来看jQuery中文文档中 ...
最新文章
- Dev-C++ v5.11
- 翻译职称计算机能力,2018年职称计算机word2003考点辅导:用好Office2003中的翻译功能...
- JAVA笔记(十四)
- CSS——Fonts(字体)
- Java校招笔试题-Java基础部分(二)
- linux系统win,Windows10安装运行linux系统的方法
- 自然语言处理基本概念及基础工具
- java定义vip顾客继承顾客_Java初级教频教程 - JavaSE - Java - 私塾在线 - 只做精品视频课程服务...
- 【07】processing-字体(中文)
- Java打印正三角形
- oracle PL/SQL 这些查询结果不可更新,请包括ROWID或使用SELECT ...FOR UPDATE 获得可
- 工具使用,PS隐藏技能—对称绘画
- 2006-01-23,科比-布莱恩特得了81分
- 伊诺ET-33夹式校(音器吉他/贝司/小提琴/尤克里里 使用
- 从飞猪智能酒店到优酷视频,探索阿里智能研发协同流程
- 课堂教学评价的主要内容
- Yelp Dataset(Yelp业务-评论-用户数据集)
- 屏幕录像功能技术探索及分享
- SQL--乱七八糟问题
- C#/Unity不允许发送UDP到255.255.255.255的解决方法
热门文章
- Node基础——认识Node
- OneHotEncoder独热编码
- python调用谷歌翻译Googletrans接口
- 中文键盘 linux,键盘和中文输入 教程
- Logstash报错:[ERROR][logstash.agent ] Failed to execute action {...
- python 抛出异常记录
- gmail+mtalk配合打免费网络电话。
- Multisim电路仿真-验证KCL和KVL
- Zabbix 3.0 版本企业微信群机器人报警
- 代码: 0x80131500:应用商店打不开