数据结构与算法————稀疏数组

引言

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

一、稀疏数组的概念

当一个数组中大部分元素是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, "复盘后的二维数组......");

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

总结

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux进阶之路————crond定时任务调度

引言 crond 的概念和 crontab 是不可分割的。crontab 是一个命令&#xff0c;而 crond 是Linux 下用来周期性执行某种任务或等待处理某些事件的守护进程&#xff0c;类似于 Windows 下的计划任务。 当装完操作系统之后&#xff0c;默认便会安装 crond 服务工具&#xff0c;并…

Linux进阶之路————Linux磁盘分区与挂载

引言 对于Linux来说&#xff0c;无论有几个分区&#xff0c;分给哪一目录使用&#xff0c;它归根结底就只有一个根目录 / &#xff0c;一个独立且唯一的文件结构&#xff0c;Linux 中每个分区都是用来组成整个文件系统的一部分。 Linux采用一种叫“载入”的处理方法&#xff…

Maven学习(五)————依赖的特性辨析

引言 在Maven 中&#xff0c;依赖有一些特性必须我们掌握&#xff0c;如依赖的传递性。 一、依赖的传递性 其实依赖的传递性非常好理解。 上图&#xff0c;如果 Maven 项目 B 已经依赖了 C &#xff0c;A 又依赖了 B&#xff0c;那么 A 不需要再在自己的pom 中重复引入 C 的…

解决pom文件第一行报错(unknown)-亲测有效

原文链接&#xff1a;https://blog.csdn.net/u010947534/article/details/93743582 问题&#xff1a; Eclipse导入maven项目时&#xff0c;或者新建一个springboot项目时&#xff0c;pom.xml文件第一行报错&#xff0c;没有错误信息提示&#xff0c;就一个Unknown&#xff0c…

Oracle中start with xx connect by prior 语句解析

Oracle中start with xx connect by prior 语句解析 ​ Oracle这种的start with语句主要对B型树的数据进行递归查询.可以指定数据树上的任一节点,然后查找到它所有的子节点或者父节点. ​ 现在有如下图的数据: 我们先想数据库插入数据,这里用到oracle的批量插入写法# 1 建表 CRE…

Java NIO ———— Buffer 缓冲区详解

引言 缓冲区是一个用于特定基本类型的容器。由java.nio 包定义&#xff0c;所有缓冲区都是 Buffer 抽象类的子类。 Java NIO 中的 Buffer &#xff0c;主要用于与NIO 通道进行交互。数据从通道存入缓冲区&#xff0c;从缓冲区取出到通道中。 一、创建缓冲区 缓冲区的本质是 …

基本类型理解巩固及补码原理总结

引言 本篇文章属于计算机基础通识&#xff0c;主要讨论&#xff1a;有符号类型、无符号类型的区别&#xff0c;byte、int 等类型的取值范围&#xff0c;最大值最小值的计算公式的由来&#xff0c;原码、反码、补码转换公式。 有符号类型与无符号类型 在 Java 中的八大基本类…

LeetCode(#118)————杨辉三角形

问题描述 给定一个非负整数 numRows&#xff0c;生成杨辉三角的前 numRows 行。 在杨辉三角中&#xff0c;每个数是它左上方和右上方的数的和。 示例: 输入: 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1] ] 实现方法 class Solution {public List<List<Intege…

JVM001_类文件结构

无关性的基石 实现语言无关性的基础是虚拟机和字节码存储格式。Java虚拟机不与任何语言绑定&#xff08;包括Java&#xff09;&#xff0c;它只与‘Class文件’这种特定的二进制文件格式所关联。Class文件中包含了Java虚拟机指令集、符号表以及其它辅助信息。出于安全考虑&…

Maven学习(六)————企业Maven项目最佳实践

引言 在《Maven学习&#xff08;三&#xff09;————Maven核心概念&#xff08;二&#xff09;》中&#xff0c;学到了Maven 继承和 Maven 聚合的概念&#xff0c;这两个概念&#xff0c;解决的问题分别是&#xff1a; 1、解决一些公共依赖统一版本的问题。 2、统一打包部署…

JVM003_属性表

属性表 预备知识 javac -g Xxx.java 在生成class文件的时候生成所有调试信息javap -v Xxx.class 输出附加信息 属性表结构 类型名称数量备注u2attribute_name_index1属性名称索引&#xff0c;指向一个CONSTANT_Utf8_info型常量的索引u4attribute_length1该属性表的长度u1in…

Lombok ——自动化方法生成器

引言 此文为简单的Lombok 演示。 Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具&#xff0c;通过使用对应的注解&#xff0c;可以在编译源码的时候生成对应的方法。简而言之&#xff0c;一句话就是&#xff1a;通过简单的注解…

LeetCode(#26)————删除排序数组中的重复项

题目 给定一个排序数组&#xff0c;你需要在原地删除重复出现的元素&#xff0c;使得每个元素只出现一次&#xff0c;返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums […

JVM006_类加载的过程

类加载 类加载时机 类加载的过程 新术语 类加载器 简单的理解为将类转换为二进制流的类或接口。 数组的元素类型 数组去掉所有维度的类型。 数组的组件类型 数组去掉一个维度的类型。 基本块 按照控制流拆分的代码块。 1. 加载 加载是类加载过程的一个阶段。加载阶段主…

服务端开发——云服务器的端口转发设置(SSH隧道)

引言 本篇博客介绍端口转发的知识&#xff0c;并详细阐述操作和设置步骤。这是因为在实际工作中&#xff0c;会有很多企业从安全的角度考虑&#xff0c;为线上或重要的服务器设置一个跳板机&#xff08;堡垒机&#xff09;&#xff0c;避免远程开发人员直接操作&#xff0c;是…

Shiro————核心设计思想

引言 以此篇博客为引&#xff0c;开启一个新的专栏分类——Shiro。 之前在工作中有比较快速的学习过Shiro安全框架&#xff0c;但经过一年的荒废&#xff0c;已经不是很熟悉了&#xff0c;通过这个系列&#xff0c;深入研究和学习Shiro的一些知识&#xff0c;填补安全管理方面…

Web应用安全————账号冻结与 Session 实时失效

引言 开篇时说些题外话&#xff0c;最近刚刚被公司CY&#xff0c;不过很快找到了下家&#xff0c;也同时拿到了三家公司的Offer。一周面试下来&#xff0c;总体感觉面试题少了&#xff0c;不过多了上机程序题。新公司是做外包&#xff0c;不过相比于上一家公司&#xff0c;也算…

Web应用安全————Shiro 解决会话固定漏洞

引言 承接上一篇《Web应用安全————账号冻结与 Session 实时失效》关于 session 的学习&#xff0c;本篇博客聚焦如何通过 shiro 解决会话固定导致的漏洞问题。 首先&#xff0c;没怎么接触过应用安全方面的小伙伴可能会发起疑问 - 什么是会话固定&#xff1f; 简单来说&…

Web应用安全————多点登录互斥

引言 在实际生活中&#xff0c;很多网站都做了多点登录互斥的操作&#xff0c;简单来说就是同一个账号&#xff0c;只能在一台电脑上登录&#xff0c;如果有人在其他地方登录&#xff0c;那么原来登录的地方就会自动下线&#xff0c;再进行操作就会弹出登录界面。 实现思路 …

Linux进阶之路————磁盘查询

引言 承接《Linux进阶之路————Linux磁盘分区与挂载》&#xff0c;本文介绍实际生产中对于磁盘的监控和查询。 一、查询磁盘整体使用情况 基本语法&#xff1a; df -h 该命令会显示包括我们手动挂载的磁盘&#xff0c;如果使用 umount 卸载磁盘&#xff0c;那么将不会显示…