稀疏矩阵,可用于矩阵的压缩,如下图(也是该代码的执行结果):
稀疏矩阵特点:首行中每一列依次代表:原矩阵行数、列数 和某行某列的值。
下面稀疏数组表示:在原矩阵(下标从0开始)第2行第3列的值为1,以此类推。
方法详解:
private static void sparseArrayCalc(int row, int col, int value) throws IOException {
// 创建8*8棋盘,这里只是一个测试用例,chessarray可以自定义传入。这里的赋值1,2代表黑白棋。
int chessarray[][] = new int[8][8];
chessarray[2][3] = 1;
chessarray[3][4] = 2;
chessarray[4][5] = 1;
chessarray[row][col] = value;
int length=chessarray.length;//记录棋盘矩阵的大小
// 棋盘中的棋子数 //这里是获取矩阵中的有效棋子的个数
int sum = 0;
for (int chessarr[] : chessarray) {
for (int data : chessarr) {
System.out.printf("%d ", data);
if (data != 0) {
sum++;//拿到矩阵中非0的值的个数
}
}
System.out.println();
}
// 构建稀疏矩阵压缩保存棋盘
int sparsearray[][] = new int[sum + 1][3];//此位置的sum+1是因为稀疏数组里,要加一行来记录原矩阵的行数、列数和值
sparsearray[0][0] = length;//原矩阵有11行
sparsearray[0][1] = length;//11列
sparsearray[0][2] = sum;//sum个非0数字
int count = 0;//count用来作为sparsearray的索引计数。
for (int i = 0; i < length; i++) {//遍历原矩阵
for (int j = 0; j < length; j++) {
if (chessarray[i][j] != 0) {//如果原棋盘矩阵第i行j列不等于0,说明有非0值
count++;//这里首先执行count++,因为稀疏矩阵第一行是用于存储,棋盘矩阵的行数,列数和值的。(也可以将上面count初始化为1,最后++)
sparsearray[count][0] = i;//记录第i行
sparsearray[count][1] = j;//记录第j行
sparsearray[count][2] = chessarray[i][j];//存储第i行第j列的值
}
}
}
count = 0;//count在下面别有用处,所以将其重新赋值0
System.out.println("chessarray的稀疏矩阵为:");
// 保存稀疏棋盘到文件中,这里进行io操作,将稀疏棋盘写到当前目录的test.txt中
FileWriter fw = new FileWriter("test.txt");//按字符将文件写入test.txt中
BufferedWriter bw = new BufferedWriter(fw);//
//这里是操作io流的基本操作
for (int sparsearr[] : sparsearray) {
System.out.printf("%d %d %d
", sparsearr[0], sparsearr[1], sparsearr[2]);
for (int data : sparsearr) {
bw.write(String.valueOf(data) + " ");//将每个sparsearr数组中的行列值写入到文件
}
bw.newLine();//换行(与/n是不同的)
}
bw.close();//这里缓冲流关闭之前,会将缓冲区写入的数据,刷新到文件
fw.close();
// 从文件中读取稀疏棋盘并恢复棋盘
System.out.println("===================================");
int chessarray2[][] = new int[sparsearray[0][0]][sparsearray[0][1]];//这里定义恢复后的棋盘矩阵,其行列大小为稀疏矩阵的首行2列
FileReader fr = new FileReader("test.txt");//文件字符输入流
BufferedReader br = new BufferedReader(fr);//缓冲字符流
String str;//用于接收缓冲区读入的字符
String datas[] = new String[sum+1];//sum+1表示整个稀疏矩阵的大小,1代表首行
while ((str = br.readLine()) != null) {//按行读入字符
//System.out.println(str);
datas[count] = str;//将每一行放入datas数组中
count++;
}
br.close();fr.close();//关闭流
count = 0;//此变量第三次使用,都用于计数。
String da[]=new String[3*(sum+1)];//由于输入流读入是按行,这里是为了存储每一个信息,每行有3列;
String d[];//临时保存棋子的位置
for (String data : datas) {
d=data.split(" ");//将每一行形如 2 3 1,将一行字符串,拆分为行列数和棋子数
for(String s:d) {
da[count]=s;//再将每个单独行数、列数、棋子保存到da数组中
count++;
}
}
//这里是将稀疏矩阵中的第三列(具体的棋子黑还是白),恢复到原棋盘8x8的位置上
for(int i=3;i<da.length;i+=3) {
chessarray2[Integer.parseInt(da[i])][Integer.parseInt(da[i+1])]=Integer.parseInt(da[i+2]);
}
System.out.println("从文件中读取稀疏矩阵-->恢复后的棋盘:");
for (int chessarr[] : chessarray2) {
for (int data : chessarr) {
System.out.printf("%d ", data);
}
System.out.println();
}
}