1:稀疏矩阵(数组)思想
以如图一个矩阵为例:有2、6、7、3、1、2、8、5、9、0这几个值,但大部分都是0,也就是无用数据,为了压缩矩阵,将该矩阵的大小(行、列数据)和非0数据的值和位置存储到一个数组中,这就是稀疏矩阵思想。
[0] | 6(行数) | 8(列数) | 9(有9个值) |
所在行 | 所在列 | 值 | |
[1] | 1 | 1 | 2 |
[2] | 1 | 5 | 6 |
[3] | 1 | 8 | 7 |
[4] | 2 | 3 | 1 |
[5] | 3 | 3 | 2 |
[6] | 3 | 7 | 3 |
[7] | 4 | 6 | 8 |
[8] | 5 | 4 | 5 |
[9] | 6 | 2 | 9 |
如上,有a[0]到a[9]一共10个向量。除了a[0]用来存储表格属性信息之外,a[1]到a[9]保存了数据所在的行、列和数据值,这10个向量组成的矩阵就是稀疏矩阵。
2:稀疏矩阵的Java实现
public class Sparse {
public static void main(String[] args) {
int[][] before = new int[][]{{1, 0, 0, 0, 5}, {0, 9, 6, 0, 0}, {-1, 0, 9, 0, 7}, {1, 2, 3, 0, 0}};
int[][] a = sparse(before);
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
public static int[][] sparse(int[][] beforeSparse) {
int validNumber = 0;//定义有效数据个数;
for (int i = 0; i < beforeSparse.length; i++) {//获取有效数据长度
for (int j = 0; j < beforeSparse[i].length; j++) {
if (beforeSparse[i][j] != 0) {
validNumber++;//有效数据的个数同样也是是稀疏矩阵的行数;
}
}
}
int[][] afterSparse = new int[validNumber + 1][3];
//获得有效数据的数量之后,就可以定义转制后系数矩阵的大小,稀疏矩阵大小为(数据量+1)*(3)
afterSparse[0][0] = beforeSparse.length;
afterSparse[0][1] = beforeSparse[0].length;
afterSparse[0][2] = validNumber;
//这三步将原矩阵的大小先存到稀疏矩阵的第0行的1、2、3列;
int k = 1;
for (int i = 0; i < beforeSparse.length; i++) {
for (int j = 0; j < beforeSparse[i].length; j++) {//通过两个for循环拿到原矩阵中非0的数据值;
if (beforeSparse[i][j] != 0) {
afterSparse[k][0] = i;
afterSparse[k][1] = j;
afterSparse[k][2] = beforeSparse[i][j];
//如果该数据值不为0,则将它的行、列、值信息一起填至k行的0、1、2位置;
//注意,k应该从1开始,因为稀疏矩阵的第0行已经存储了原矩阵的属性信息;
k++;
}
}
}
return afterSparse;
}
}
输出结果如下(注意最后一组,后面犯的错误就会导致不停输出最后一组):
4 5 10
0 0 1
0 4 5
1 1 9
1 2 6
2 0 -1
2 2 9
2 4 7
3 0 1
3 1 2
3 2 3
个人所犯错误记录:
for (int i = 0; i < beforeSparse.length; i++) {
for (int j = 0; j < beforeSparse[i].length; j++) {
//通过两个for循环拿到原矩阵中非0的数据值;
if (beforeSparse[i][j] != 0) {
for (int k = 1; k < afterSparse.length; k++) {
afterSparse[k][0] = i;
afterSparse[k][1] = j;
afterSparse[k][2] = beforeSparse[i][j];
}
//如果该数据值不为0,则将它的行、列、值信息一起填至k行的0、1、2位置;
//注意,k应该从1开始,因为稀疏矩阵的第0行已经存储了原矩阵的属性信息;
}
}
}
/*(输出结果如下(只有正确答案的最后一组):
4 5 10
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
3 2 3
*/
如图所示,错误使用了三个for循环来试图给稀疏矩阵赋值,但其实程序在进入第三个for循环后,只要原矩阵遍历到不为0的元素,都会给afterSprase矩阵重复赋值k=1到k=afterSprase.length次;例如在原矩阵[0,0]处元素为1,符合条件进入第三个循环,在该处for循环就给稀疏数组赋值了afterSprase.length-1次,而在第三个for循环结束后,当检测到又有一个元素不为0时又会重复赋值afterSprase.length-1,因此这是不正确的,最后显示的结果将会是最后一个非0数据处的10次重复(前面输出结果的最后一组数据)。