-
需求:编写五子棋游戏中,有存盘退出和续上盘的功能。一般使用二维数组来记录棋盘,如果棋盘某个点为空的则对应二维数组的值为0,若对应位置为黑棋则对应位置为1为白棋则对应位置为2
-
分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据
-
解决:稀疏数组
稀疏数组介绍
-
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组
-
稀疏数组的处理方式是:
-
记录数组一共有几行几列,有多少个不同值
-
把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
-
-
如下图:左边为原始数组,右边是稀疏数组
由图可得对于该稀疏数组[0]号元素近似是为二维数组存储分别为行的个数6,列的个数7,以及有效值(不同于数组中大多数元素的值)的个数8,对于[1]号元素表示第一个有效数字得相关信息:几列:0(第一)列,几行:3(第四)行,值的大小:8
package com.kuang.array; public class ArrayDemo08 { public static void main(String[] args) { //1.创建一个二维数组 11*11 0代表没有棋子,1:黑棋 2:白旗 int[][] array1 = new int[11][11];//新建一个11*11的二维数组初始为默认值均为0 array1[1][2] = 1; array1[2][3]=2; //输出原始的数组 System.out.println("输出原始的数组"); for (int[] ints : array1) {//for each循环只适用于一位数组此时对于此二维数组的某个元素为一位数组故而内部还应该有一个for each循环 for (int anInt : ints) {//for each循环的使用方法为:数组名.for+Enter既可以实现按顺序调用数组中的某个元素此时ints即为一位数组即成功输出 System.out.print(anInt+"\t"); } System.out.println(); } System.out.println("=================="); //转换为稀疏数组来保存 //先获取有限制的个数sum int sum=0; for (int i = 0; i <11 ; i++) { for (int j = 0; j <11 ; j++) { if(array1[i][j]!=0){ sum++; } } } System.out.println("有效值的个数:"+sum); //2.创建一个稀疏数组对应的数组 int[][] array2 = new int[sum+1][3];//首先按图得数组行数为有效值数目+1,列为固定的3列 array2[0][0]=11;//数组有11行 array2[0][1]=11;//11列 array2[0][2]=sum;//有2个有效值 //遍历二维数组,将非0的值,存放在稀疏数组中 int count = 0; for (int i = 0; i <array1.length ; i++) { for (int j = 0; j <array1[i].length ; j++) { if(array1[i][j]!=0){ count++; array2[count][0]=i;//对应有效值所在行 array2[count][1]=j;//所在列 array2[count][2]=array1[i][j];//所对应的值 } } } //输出稀疏数组 System.out.println("稀疏数组:"); for (int i = 0; i <array2.length ; i++) { System.out.println(array2[i][0]+"\t" +array2[i][1]+"\t"+array2[i][2]+"\t");//因为列数为固定的所以不必双层循环去打印所有元素 } System.out.println("=================="); System.out.println("还原"); //1.读取稀疏数组的值 int[][] array3 = new int[array2[0][0]][array2[0][1]];//即为int[行数][列数] //2.给其中的元素还原它的值 for (int i = 1; i <array2.length ; i++) {//表示仅对有效数进行赋值到array3的操作 array3[array2[i][0]][array2[i][1]]=array2[i][2]; } //3.打印 System.out.println("输出还原的数组"); for (int[] ints : array3) {//for each循环只适用于一位数组此时对于此二维数组的某个元素为一位数组故而内部还应该有一个for each循环 for (int anInt : ints) {//for each循环的使用方法为:数组名.for+Enter既可以实现按顺序调用数组中的某个元素此时ints即为一位数组即成功输出 System.out.print(anInt+"\t"); } System.out.println(); } } }
代码较长主要就是针对刚开始的图片对应棋盘的某个二维数组array1利用二维稀疏数组array2将其压缩到其中以减小内存的使用,最后再将二维稀疏数组array2解压缩为array3并观察是否与array1一致。即可验证解压缩的实现与稀疏数组的功效。
首先定义了一个11行11列的数组array1并且由于默认值均为0故而不需要对其它元素进行赋值,之后单独对于有效值进行赋值即可实现对于压缩前的数组array1的初始化。利用两遍for-each循环(某个数组的for-erch循环的打开方式:数组名.for+Enter即可)for-each循环为依次调用循环中的元素但是二维数组的元素实际上为一维数组故而要使用嵌套两层的for-each循环来实现,但是要注意对于变量的使用。对于二维数组array1的每个元素的调用以及打印观察是否初始化正确!
第二步为将初始化数组array1进行压缩处理,首先确定初始化数组的有效数的个数直接两层for循环遍历所有元素判断其中不等于0的元素个数为sum个。之后先定义稀疏数组array2为num+1行(由图得除了包含有效数的行数还包含一行总结行)为3列是固定的。之后对array2进行赋值操作:对于array2第一行的数据可以直接进行赋值因为已经由array1得情况得知其总共多少行,多少列,由多少有效值(即为第一行的数据)对于1-num行的数据则为对array1进行遍历找到对应的有效值并得到其对应的行与列和值并依次赋值给array2的1-num行的数据,至此即将稀疏数组array2完成了赋值,可以直接利用一层循环查看是否正确(之所以不用两层是因为列固定为3列不需要两层训话嵌套)至此第二步也完成。
第三步:是将已经压缩完毕的稀疏数组array2进行解压缩处理定义一个新的11行11列(实际上如果事先不知道压缩前的行列数可以通过稀疏数组0行第一个和第二个元素的调用来实现)的二维数组arrays来保存所有数据,由于要赋值的是针对有效值进行的故而循环调用array2的次数也就是array2.length-1次(有效数的个数),之后再根据某行的首个元素与第二个元素来确定该有效值应位于array3的哪行与哪列,最后直接调用某行的第三个元素将有效数的值赋值给array3中对应行列得元素。
第四步:显示压缩完毕后的还原数组并与原数组array1进行比较查看还原是否成功。方法:两次for-each循环来实现(for (int[] ints : array3){}//此次为对于二维数组的for-each实际上每次调用的为一位数组ints,故而对于ints还应执行一次for-each循环 for (int anInt : ints)),最后对于ints中的元素anInt直接调用输出函数System.out.print(anInt+"\t");即可实现,最后内层循环(也就是某行元素)结束后,调用System.out.println();实现换行操作,即可成功打印。至此实例的稀疏数组的压缩与解压缩操作已经完成!