稀疏数组是一种表示稀疏矩阵的数据结构。(在编程中,我们常以二维数组来表示矩阵)
一个矩阵被称为稀疏矩阵,当其中大部分元素都是0时。
稀疏数组通过记录非零元素的行、列和值来表示一个稀疏矩阵,从而节省存储空间。
具体地说,稀疏数组通常以三列形式存储:第一列表示非零元素的行,第二列表示非零元素的列,第三列表示非零元素的值。
不过第一行有点特殊,具体看图
类似于这样:
例如一个8行8列的稀疏矩阵,里面有三个有效的元素(颜色为红色的)需要我们记录:
第一行,我们知道了矩阵是8*8的,同时知道矩阵中有效元素有3个,然后剩下的三行就把有效元素的行列坐标与值依次填入就行。
稀疏矩阵的存储:
对于一个非常大的矩阵,如果其中大部分元素都是0,那么可以使用稀疏数组来存储这个矩阵,从而节省存储空间。
图像处理:
在图像处理中,通常需要处理大量的像素,而大部分像素的取值都是相同的。这时候可以使用稀疏数组来存储图像数据,只记录非零的像素值,从而节省存储空间和加快处理速度。
网络图:
在网络图中,通常需要记录节点之间的连接关系。如果节点之间的连接关系比较稀疏,可以使用稀疏数组来存储连接关系,只记录存在连接的节点,从而节省存储空间和加快处理速度。
后面两个比较高级,我还没真正使用过,所以我只用第一个用途为例。
int[][] sparseArrays=new int[8][8];
//假设里面只有3个有效数据
sparseArrays[2][3]=1;
sparseArrays[3][4]=2;
sparseArrays[6][3]=3;
当然也可以采用动态创建或者利用Java中的集合来动态添加,这里就不用那些复杂的了
第一步:遍历待压缩矩阵,提取有效元素个数
int value_sum=0;//有效数据的总数
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
value_sum++;
}
}
}
遍历完成后就能得到有效元素的个数
第二步:创建压缩数组,将值写入
int[][] compressed_arrays=new int[value_sum+1][3];
第三步:压缩后的数组首行对应分别是稀疏数组的行,列,有效值总数
compressed_arrays[0][0]=sparseArrays.length;
compressed_arrays[0][1]=sparseArrays[0].length;
compressed_arrays[0][2]=value_sum;
第四步:再次遍历矩阵,将有效元素的行列坐标和值拿到
int count=0;//临时计数器
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
compressed_arrays[count+1][0]=i;
compressed_arrays[count+1][1]=j;
compressed_arrays[count+1][2]=sparseArrays[i][j];
//将具体的有效值插入到压缩中的数组中
count++;
}
}
}
//展示压缩后的数组
for (int i = 0; i < compressed_arrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < compressed_arrays[i].length; j++) {
System.out.printf("%d\t",compressed_arrays[i][j]);
}
System.out.println("]");
}
恢复稀疏数组成稀疏矩阵
System.out.println("恢复成正常数组");
int[][] normalArrays=new int[compressed_arrays[0][0]][compressed_arrays[0][1]];
for (int i=1;i<compressed_arrays.length;i++){
normalArrays[compressed_arrays[i][0]][compressed_arrays[i][1]]=compressed_arrays[i][2];
}
for (int i = 0; i < normalArrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < normalArrays[i].length; j++) {
System.out.printf("%d\t",normalArrays[i][j]);
}
System.out.println("]");
}
顺便加上了几次输出,让过程更明显
public class SparseArrays {
//自己创建一个稀疏数组
public static void main(String[] args) {
int[][] sparseArrays=new int[8][8];
//假设里面只有3个有效数据
sparseArrays[2][3]=1;
sparseArrays[3][4]=2;
sparseArrays[6][3]=3;
//二维数组打印遵循先行后列的嵌套循环
for (int i = 0; i < sparseArrays.length; i++) {//这里的length字段是二维数组的行数
System.out.printf("[\t");
for (int j = 0; j < sparseArrays[i].length; j++) {//这里的length字段反映的是二维数组所在行的长度
System.out.printf("%d\t",sparseArrays[i][j]);
}
System.out.println("]");
System.out.println();
}
// 第一步:遍历待压缩数组,提取有效信息。
int value_sum=0;//有效数据的总数
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
value_sum++;
}
}
}
System.out.println("将其进行压缩");
//第二步:创建压缩数组,将值写入
int[][] compressed_arrays=new int[value_sum+1][3];
//压缩后的数组首行对应分别是稀疏数组的行,列,有效值总数
compressed_arrays[0][0]=sparseArrays.length;
compressed_arrays[0][1]=sparseArrays[0].length;
compressed_arrays[0][2]=value_sum;
int count=0;//临时计数器
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
compressed_arrays[count+1][0]=i;
compressed_arrays[count+1][1]=j;
compressed_arrays[count+1][2]=sparseArrays[i][j];//将具体的有效值插入到压缩中的数组中
count++;
}
}
}
//展示压缩后的数组
for (int i = 0; i < compressed_arrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < compressed_arrays[i].length; j++) {
System.out.printf("%d\t",compressed_arrays[i][j]);
}
System.out.println("]");
}
//恢复压缩数组成正常数组
System.out.println("恢复成正常数组");
int[][] normalArrays=new int[compressed_arrays[0][0]][compressed_arrays[0][1]];
for (int i=1;i<compressed_arrays.length;i++){
normalArrays[compressed_arrays[i][0]][compressed_arrays[i][1]]=compressed_arrays[i][2];
}
for (int i = 0; i < normalArrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < normalArrays[i].length; j++) {
System.out.printf("%d\t",normalArrays[i][j]);
}
System.out.println("]");
}
}
}
这里本质就是将读取内存里的稀疏矩阵和稀疏数组和输出,变成读取存储里的文件数据再转化为内存里的稀疏数组和稀疏矩阵的形式。不做详细介绍了,这里给个将稀疏数组存储到文件中以达到持久化的例子。
记得文件路径改成自己的。
package com.budiu;
/**
结合IO流运用稀疏数组
*/
import java.io.*;
public class SparseArrays_IO {
public static void main(String[] args) throws IOException {
int[][] sparseArrays=new int[8][8];
//假设里面只有三个有效数据
sparseArrays[2][3]=1;
sparseArrays[3][4]=2;
sparseArrays[6][3]=3;
//二维数组打印遵循先行后列的嵌套循环
for (int i = 0; i < sparseArrays.length; i++) {//这里的length字段是二维数组的行数
System.out.printf("[\t");
for (int j = 0; j < sparseArrays[i].length; j++) {//这里的length字段反映的是二维数组所在行的长度
System.out.printf("%d\t",sparseArrays[i][j]);
}
System.out.println("]");
System.out.println();
}
// 第一步:遍历待压缩数组,提取有效信息。
int value_sum=0;//有效数据的总数
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
value_sum++;
}
}
}
System.out.println("将其进行压缩");
//第二步:创建压缩数组,将值写入
int[][] compressed_arrays=new int[value_sum+1][3];
//压缩后的数组首行对应分别是稀疏数组的行,列,有效值总数
compressed_arrays[0][0]=sparseArrays.length;
compressed_arrays[0][1]=sparseArrays[0].length;
compressed_arrays[0][2]=value_sum;
int count=0;//临时计数器
for (int i = 0; i < sparseArrays.length; i++) {
for (int j = 0; j < sparseArrays[i].length; j++) {
if(sparseArrays[i][j]!=0) {
compressed_arrays[count+1][0]=i;
compressed_arrays[count+1][1]=j;
compressed_arrays[count+1][2]=sparseArrays[i][j];//将具体的有效值插入到压缩中的数组中
count++;
}
}
}
//展示压缩后的数组
for (int i = 0; i < compressed_arrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < compressed_arrays[i].length; j++) {
System.out.printf("%d\t",compressed_arrays[i][j]);
}
System.out.println("]");
}
//将压缩数组写入到文件中
//创建IO流
File file=new File("D:\\javaworkspace\\note\\data_structure\\src\\file\\map.data");
FileOutputStream fos=new FileOutputStream(file);
BufferedOutputStream bos=new BufferedOutputStream(fos);
for (int i = 0; i < compressed_arrays.length; i++) {
for (int j = 0; j < compressed_arrays[i].length; j++) {
bos.write((compressed_arrays[i][j]+"\t").getBytes());
}
bos.write("\n".getBytes());
}
bos.close();
//
FileReader fr=new FileReader(file);
BufferedReader reader=new BufferedReader(fr);
int bytesSize=0;
byte[] bytes=new byte[1024];
int count1=0;
String content=null;
int[][] compressed_arrays1=null;
while ((content=reader.readLine())!=null){
//将字节转化为字符
String[] tmp=content.split("\t");
int row=Integer.parseInt(tmp[0]);
int column=Integer.parseInt(tmp[1]);
int value=Integer.parseInt(tmp[2]);
count1++;
if(count1==1){
compressed_arrays1=new int[value+1][3];
}
compressed_arrays1[count1-1][0]=row;
compressed_arrays1[count1-1][1]=column;
compressed_arrays1[count1-1][2]=value;
}
//恢复压缩数组成正常数组
System.out.println("恢复成正常数组");
int[][] normalArrays=new int[compressed_arrays1[0][0]][compressed_arrays1[0][1]];
for (int i=1;i<compressed_arrays1.length;i++){
normalArrays[compressed_arrays1[i][0]][compressed_arrays1[i][1]]=compressed_arrays1[i][2];
}
for (int i = 0; i < normalArrays.length; i++) {
System.out.printf("[\t");
for (int j = 0; j < normalArrays[i].length; j++) {
System.out.printf("%d\t",normalArrays[i][j]);
}
System.out.println("]");
}
}
}