开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情
介绍
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
1)记录数组一共有几行几列,有多少个不同的值
2)把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
二维数组
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 22 | 0 | 0 | 15 |
| 1 | 0 | 11 | 0 | 0 | 0 | 17 | 0 |
| 2 | 0 | 0 | 0 | -6 | 0 | 0 | 0 |
| 3 | 0 | 0 | 0 | 0 | 0 | 39 | 0 |
| 4 | 91 | 0 | 0 | 0 | 0 | 0 | 0 |
| 5 | 0 | 0 | 28 | 0 | 0 | 0 | 0 |
稀疏数组
| 行(row) | 列(col) | 值(value) | |
|---|---|---|---|
| [0] | 6 | 7 | 8 |
| [1] | 0 | 3 | 22 |
| [2] | 0 | 6 | 15 |
| [3] | 1 | 1 | 11 |
| [4] | 1 | 15 | 17 |
| [5] | 2 | 3 | -6 |
| [6] | 3 | 5 | 39 |
| [7] | 4 | 0 | 91 |
| [8] | 5 | 2 | 28 |
第一行记录原二维数组的大小,和拥有值的个数
应用实例
使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等),把稀疏数组存盘,并且可以从新恢复原来的二维数组数。(棋盘保存复盘)
创建二维数组
根据上图所示创建二维数组11*11
//原始二维数组11*11
int chessArr1[][] = new int[11][11];
//1代表黑子,2代表蓝子
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
//遍历二维数组
System.out.println("原始二维数组");
for (int[] ints : chessArr1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
二维数组存放原始棋盘成功!
获取稀疏数组
遍历原始数组
遍历原始数组得到二维数组也就是棋盘中当前的棋子个数有多少(值不为0的个数),用变量count表示
//将二维数组转换为稀疏数组
//1.先遍历二维数组,得到非0的数据个数。
int count = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1.length; j++) {
//不为零代表有棋子
if (chessArr1[i][j] != 0) count++;
}
}
创建稀疏数组
根据遍历原始二维数组获取到当前棋子的个数count,创建稀疏数组,行为count+1(有一行记录原始二维数组的行,列数,值数),列为3(行,列,值)。
//2.创建对应的稀疏数组,存放的数据个数+1行,列为固定3列即可,分别记录row,column,value
int[][] sparseArr = new int[count + 1][3];
//给稀疏数组赋值
sparseArr[0][0] = chessArr1.length;
sparseArr[0][1] = chessArr1[0].length;
sparseArr[0][2] = count;
第一行记录原始二维数组的行,列数,值数
sparseArr[0][0] = chessArr1.length;行数sparseArr[0][1] = chessArr1[0].length;列数sparseArr[0][2] = count;值数
稀疏数组赋值
遍历原始二维数组给稀疏数组赋值,当原始二维数组值不为0时,代表此位置有值,将其行列数和值存放到稀疏数组中。
//2.给稀疏数组赋值
int sum = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if (chessArr1[i][j] != 0) {
sum++;
sparseArr[sum][0] = i;//存放原数组中row
sparseArr[sum][1] = j;//存放原数组中column
sparseArr[sum][2] = chessArr1[i][j];//存放原数组中该位置的value值
}
}
}
//遍历稀疏数组
System.out.println();
System.out.println("稀疏数组");
for (int i = 0; i < sparseArr.length; i++) {
for (int j = 0; j < sparseArr.length; j++) {
System.out.print(sparseArr[i][j] + "\t");
}
System.out.println();
}
sum++放在最前头,是初始值为0,而我们稀疏数组0行中的值已经存放了原始数组的信息,从1行中开始存放棋子
sparseArr[sum][0] = i;//存放原数组中row
sparseArr[sum][1] = j;//存放原数组中column
sparseArr[sum][2] = chessArr1[i][j];//存放原数组中该位置的value值
还原原始数组
创建二维数组
得到稀疏数组中第0行中存放有关原始二维数组的数据,row,column,value。通过row和column创建出还原的二维数组。(这里的value值可以为0,我没用到这个存放值)
//将稀疏数组转换为二维数组
//1.得到稀疏数组中的第一行存放有关二维数组的值
int row = sparseArr[0][0];//原二维数组的行
int column = sparseArr[0][1];//原二维数组的列
int value = sparseArr[0][2];//原二维数组的存放的值个数
遍历稀疏数组
从(0开始)第1行开始遍历稀疏数组,得到每行中存放的row,column,value。再根据row和column即可代入新的二维数组中定位到位置,将value赋值给该点即可。
row = sparseArr[i][0];
column = sparseArr[i][1];
value = sparseArr[i][2];
chessArr2[row][column] = value;
//还原而成的二维数组
int[][] chessArr2 = new int[row][column];
//遍历稀疏数组存放的值,将其按对应顺序存放到二维数组中。没赋值的初始化默认为0
for (int i = 1; i <sparseArr.length ; i++) {
for (int j = 1; j <sparseArr[i].length ; j++) {
//遍历稀疏数组存放的值,将其按对应顺序存放到二维数组中
row = sparseArr[i][0];
column = sparseArr[i][1];
value = sparseArr[i][2];
chessArr2[row][column] = value;
}
}
//遍历根据稀疏数组转换的二维数组
System.out.println();
System.out.println("新二维数组");
for (int[] ints : chessArr2) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
存放稀疏数组
写入文件
在通过遍历原始二维数组创建稀疏数组之后,通过io流将稀疏数组写到chess.data文件
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("chess.data"));
//遍历稀疏数组
System.out.println();
System.out.println("稀疏数组");
for (int i = 0; i < sparseArr.length; i++) {
for (int j = 0; j < sparseArr[i].length; j++) {
fileOutputStream.write(sparseArr[i][j]);
System.out.print(sparseArr[i][j] + "\t");
}
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
读取文件
通过读取先前写入到硬盘中chess.data文件,创建出稀疏数组,从而通过稀疏数组还原原始二维数组。
FileInputStream fileInputStream = null;
int sparseArr2[][] = null;
try {
//将稀疏数组从磁盘的文件中读取出来
fileInputStream = new FileInputStream(new File("chess.data"));
sparseArr2 = new int[count + 1][3];
for (int i = 0; i < sparseArr2.length; i++) {
for (int j = 0; j < sparseArr2[i].length; j++) {
sparseArr2[i][j] = fileInputStream.read();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
public class sparseArrayIO {
public static void main(String[] args) {
//原始二维数组11*11
int chessArr1[][] = new int[11][11];
//1代表黑子,2代表蓝子
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
//遍历二维数组
System.out.println("原始二维数组");
for (int[] ints : chessArr1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
//将二维数组转换为稀疏数组
//1.先遍历二维数组,得到非0的数据个数。
int count = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1.length; j++) {
//不为零代表有棋子
if (chessArr1[i][j] != 0) count++;
}
}
//2.创建对应的稀疏数组,存放的数据个数+1行,列为固定3列即可,分别记录row,column,value
int[][] sparseArr = new int[count + 1][3];
//给稀疏数组赋值
sparseArr[0][0] = chessArr1.length;
sparseArr[0][1] = chessArr1[0].length;
sparseArr[0][2] = count;
//2.给稀疏数组赋值
int sum = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if (chessArr1[i][j] != 0) {
sum++;
sparseArr[sum][0] = i;//存放原数组中row
sparseArr[sum][1] = j;//存放原数组中column
sparseArr[sum][2] = chessArr1[i][j];//存放原数组中该位置的value值
}
}
}
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("chess.data"));
//遍历稀疏数组
System.out.println();
System.out.println("稀疏数组");
for (int i = 0; i < sparseArr.length; i++) {
for (int j = 0; j < sparseArr[i].length; j++) {
fileOutputStream.write(sparseArr[i][j]);
System.out.print(sparseArr[i][j] + "\t");
}
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileInputStream fileInputStream = null;
int sparseArr2[][] = null;
try {
//将稀疏数组从磁盘的文件中读取出来
fileInputStream = new FileInputStream(new File("chess.data"));
sparseArr2 = new int[count + 1][3];
for (int i = 0; i < sparseArr2.length; i++) {
for (int j = 0; j < sparseArr2[i].length; j++) {
sparseArr2[i][j] = fileInputStream.read();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println();
System.out.println("从磁盘中读取的稀疏数组");
for (int[] is : sparseArr2) {
for (int i : is) {
System.out.print(i + "\t");
}
System.out.println();
}
System.out.println();
//将稀疏数组转换为二维数组
//1.得到稀疏数组中的第一行存放有关二维数组的值
int row = sparseArr[0][0];//原二维数组的行
int column = sparseArr[0][1];//原二维数组的列
int value = sparseArr[0][2];//原二维数组的存放的值个数
int[][] chessArr2 = new int[row][column];
//遍历稀疏数组存放的值,将其按对应顺序存放到二维数组中。没赋值的初始化默认为0
for (int i = 1; i < sparseArr.length; i++) {
for (int j = 1; j < sparseArr[i].length; j++) {
//遍历稀疏数组存放的值,将其按对应顺序存放到二维数组中
row = sparseArr[i][0];
column = sparseArr[i][1];
value = sparseArr[i][2];
chessArr2[row][column] = value;
}
}
//遍历根据稀疏数组转换的二维数组
System.out.println();
System.out.println("新二维数组");
for (int[] ints : chessArr2) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
}