这里首先提出一个实际的例子:五子棋程序.在五子棋中,两个人下完棋之后可以将下好的棋存在文件中,或者说因突然有事,两个人无法继续下五子棋,这个时候就需要将五子棋下的位置记录起来存到文件中去.
如何存储五子棋盘?这里我们可以用到二维数组,没下的点可以用0表示,下的白棋用1表示,下的黑棋可以用2,表示.:
如上图所示:有一个明显的问题,如何说存放的0太多了,这样就没有了意义.所以我们需要想一个办法,如何将该存储五子棋盘做一个优化,这个时候提出了另外一个数组, 稀疏数组.
在稀疏数组中,我们可以存放有用的数据,也就是说在稀疏数组中存储非0数据.
稀疏数组如何存储有用的数据?
首先我们需要清楚的是稀疏数组的结构:
稀疏数组也是一个二维数组,固定的3列:分别为行(row),列(col),值(value)
行和列代表的是第一个有用数值处于的二维数组中的第几行个第几列.
值就是这个有用数值的具体值.如图:
这样就用稀疏数组优化了二维数组.但是这里有一个限制条件就是在有用值相对较少的情况下,如果说一个二维数组存满了值,是不适用稀疏数组的
二维数组如何转化成稀疏数组?
思路:
首先为了完成稀疏数组的转化,我们需要得出稀疏数组的第一行的行列值
:
1.得出该二维数组整体有多少行,有多少列
2.得出该二维数组具体有多少个数据
3.通过循环,得出具体非0数值所处的行列值.
4.由于稀疏数组的列值固定为三,通过2可以知道二维数组中有用值的个数
,所以得出了稀疏数组的行数,
5.通过二维数组的行列,得出具体的数值,存放在稀疏数组的value中
然后我们来看看实例代码:
package com.qiu.sparsearray;
public class SparseArray {
public static void main(String[] args) {
//先创建一个原始的二维数组
//0:表示没有棋子,1:表示白子,2:表示黑子
int chessArr1[][] = new int[11][11];//表示一个11*11的原始棋盘
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
System.out.println("原始的二维数组-------------------");
//输出原始二维数组
for (int[] row : chessArr1){
for ( int data :row){
// System.out.println(row);//这种打印的是该数组地址的哈希
//System.out.printf("%d\t",data);//printf可以定义输出的格式
System.out.printf(data+"\t");
}
System.out.println();
}
//将二维数组转成稀疏数组的思想
//1.现遍历二维数组,得到非0数据的个数
int sum =0;
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j <chessArr1.length ; j++) {
if (chessArr1[i][j]!= 0){
sum++;
}
}
}
System.out.println("sum="+sum);
//创建对应的稀疏数组
int sparseArray[][]= new int[sum+1][3];
//给稀疏数组赋值
//首先定义第一行的数据
sparseArray[0][0] = chessArr1.length;//表示有多少行
sparseArray[0][1] = chessArr1.length;//表示有多少列
sparseArray[0][2] = sum;//表示有多少个值
//将二维数组的非0值存放到稀疏数组中
int count = 0; //记录这是第几个非0数据
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if (chessArr1[i][j] != 0) {
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = chessArr1[i][j];
//解释一下,由于稀疏数组是记录非0值的,所以说在记录非0值时,需要存储该数据二维数组的横纵坐标,所以说需要将ij赋值给第0列
//和第一列,第二列就是该非0的值
}
}
}
System.out.println("------------------------------");
System.out.println("得到的稀疏数组为:");
for (int i = 0; i <sparseArray.length ; i++) {
//System.out.printf("%d\t%d\t%d\t\n",sparseArray[i][0],sparseArray[i][1],sparseArray[i][2]);
System.out.printf("%d\t%d\t%d\t\n",sparseArray[i][0],sparseArray[i][1],sparseArray[i][2]);
}
System.out.println();
}
}
运行的结果为:
上述实现了五子棋盘的存储,但是如果我们需要从该文件中读取出棋盘的位置,也就需要将文件中的稀疏数组,恢复成一个正规的二维数组,这个时候我们再来理一理恢复的思路:
1.拿到稀疏数组之后,我们需要根据稀疏数组中的第一行的数据,得知该二维数组的原始结构
2.再读取稀疏数组的后几行数据,并赋值给原始的二维数组即可
//将稀疏数组恢复成原始的二维数组
/*
1.先读取稀疏数组的第一行,根据第一行的数据创建原始的二维数组
2.再读取稀疏数组后面的几行的数据,并复制给原始的二维数组即可
*/
//1.先读取稀疏数组的第一行,根据第一行的数据创建原始的二维数组
int chessArray2[][] =new int[sparseArray[0][0]][sparseArray[0][1]];
//2.再读取稀疏数组后面的几行的数据,并复制给原始的二维数组即可
//sparseArray[i][0]:行,sparseArray[i][1]:列 ,sparseArray[i][2]:具体值
for (int i = 1; i <sparseArray.length ; i++) {
chessArray2[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
//输出恢复后的二维数组
System.out.println("恢复后的稀疏数组-----------");
for (int[] row : chessArray2){
for (int data : row){
System.out.printf("%d\t",data);
}
System.out.println();
}
}
结果如下: