又是一个实验题:三元数组存储稀疏矩阵,同时实现基本的加法,减法,乘法,求逆
思路:
首先规范好输入情况
明确三元数组的数据结构和输入特征( 行优先输入
)
将稀疏矩阵建立成三元数组和三元数组转化输出
数组的加法,减法(
根据输入的行与列来判断是否可以进行
最后的运算结果仍是稀疏矩阵
输出结果为矩阵
)
思路实现
明确三元数组的数据结构和输入特征( 行优先输入
)
typedef struct
{
int row;
int col;
ElementType value;
}Triple;
typedef struct
{
Triple data[MAXSIZE];
int rows,cols,nums;//非零起
}TSMatrix;
将稀疏矩阵建立成三元数组和三元数组转化输出
PtrTSMatrix CreatMatrix( void ) { int count = 0; PtrTSMatrix Matrix; Matrix = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) ); if( Matrix == NULL ) { printf("Not Space\n "); exit( 0 ); } printf("输入行与列\n"); scanf("%d%d",&Matrix->rows,&Matrix->cols); printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)\n"); scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value); while( Matrix->data[count].row != -1 ) { count++; scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value); if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 ) { printf("未按行输出:\n"); getchar(); exit(0); }//if }//while Matrix->nums = count; return Matrix; }/* CreatMatrix */ /* print the matrix Matrix by using matrix */ void PrintMatrix( PtrTSMatrix Matrix ) { int i,j; int count = 0; for( i=0; i<Matrix->rows; i++ ) { for( j=0; j<Matrix->cols; j++ ) { if( count<Matrix->nums && i==Matrix->data[count].row-1 && j==Matrix->data[count].col-1 ) { printf("%2d",Matrix->data[count].value); count++; } else { printf("%2d",0); }//if-else }//for printf("\n"); }//for }/* PrintMatrix */ PtrTSMatrix CreatMatrix( void ) { int count = 0; PtrTSMatrix Matrix; Matrix = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) ); if( Matrix == NULL ) { printf("Not Space\n "); exit( 0 ); } printf("输入行与列\n"); scanf("%d%d",&Matrix->rows,&Matrix->cols); printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)\n"); scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value); while( Matrix->data[count].row != -1 ) { count++; scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value); if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 ) { printf("未按行输出:\n"); getchar(); exit(0); }//if }//while Matrix->nums = count; return Matrix; }/* CreatMatrix */
数组的加法,减法(
根据输入的行与列来判断是否可以进行
最后的运算结果仍是稀疏矩阵
)
一般人最先想到的是两个for循环吧,那么算法的效率为 O( M *N ),我将算法稍稍改进了一下,优化到了 O(M+N ),具体思路如下
1 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
x | y | vaule |
类似上面那个三元组,在一个矩阵中想要确认位置需要x,y两个数据,实际上我可以把它回归到它在内存中存储得形式,即是线性存储,每一元素有唯一得一个对应值(假设矩阵为3×3),这样在就可以在一次循环中比较了
1 | 1 |
5 | 2 |
9 | 3 |
flag | vaule |
while( 没有一个三元组被遍历完 )
{
if(俩个三元组位置相同)
{
将两个三元组得位置信息和和传递给新的三元组
两个三元组都向后移一位
}
elseif( 其中一个三元组的元素在另一个之前 )
{
将位于前面得元素的位置信息和值传给新得三元组
向后移一位
}
}
/* Plus A and B ,return C */
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
int i=0,j=0;//标记追逐 A B
PtrTSMatrix C;//存放和
if( A->rows!=B->rows || A->cols!=B->cols )
{
return NULL;
}
C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
C->rows = A->rows;
C->cols = A->cols;
C->nums = -1; //初始化
while( i<A->nums && j<B->nums )
{
if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
{
if( A->data[i].value+B->data[j].value != 0 )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value+B->data[j].value;
}
i++;
j++;//标记后移
}
else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
else
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}//if-else
}//while,
if( i == A->nums )
{
while( j < B->nums )
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}
}
else
{
while( i < A->nums )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
}//if-else
C->nums++;
return C;
}//AddMatrix
矩阵乘法的实现:
。
原文链接 (详细的解释了原理和B矩阵的两个辅助矩阵构造,但对于算法的实现没有详讲)
总得来说,在稀疏矩阵中,C=A乘B是对应行和对应列中非零值的事,例如在A 中 i 行中的第一个非零值 A[i][j],可以和它相乘的只有B的 j 行的非零值B[j][k],而且相乘结果还是放在C[i][k]中,这样把A中的非零值都与
如果给你一张纸来计算A×B,你肯定会先是A的第一行和B的第一列相乘,放在C[0][0]的位置,之后是和B的第二列相乘,放在C[0][1]中,当B的列算到头后,再从A的第二行开始,是吧?但要让计算机对三元组这样操作显然不行,因为你很难确定B三元组的任意一列(当然你要转置,我自然不说什么)。
那么该怎么做呢?
A 0 1 0 1 B 1 0 0 C = ?
0 0 1 0 3 2 0
0 1 0
0 0 2
首先从A中取的第一个值,这个值是 [ 1 2 1 ]([]内的值分别表示其x,y,vaule),那么在整个乘法过程中能和这个值相乘的也只有B中的第二行的[ 2 1 3 ] ,[ 2 2 2]
并且是放在C的第一行中的不同列的。那么能这么干嘛
(1).从A三元组中按顺序取一值 [ x y z ],那么找到对应的B的y
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
int i=0,j=0;//标记追逐 A B
PtrTSMatrix C;//存放和
if( A->rows!=B->rows || A->cols!=B->cols )
{
return NULL;
}
C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
C->rows = A->rows;
C->cols = A->cols;
C->nums = -1; //初始化
while( i<A->nums && j<B->nums )
{
if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
{
if( A->data[i].value+B->data[j].value != 0 )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value+B->data[j].value;
}
i++;
j++;//标记后移
}
else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
else
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}//if-else
}//while,
if( i == A->nums )
{
while( j < B->nums )
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}
}
else
{
while( i < A->nums )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
}//if-else
C->nums++;
return C;
}//AddMatrix
下面是可直接编译运行的代码:
/*************************************************************************
> File Name: Matrix.c
> Author: zh
> Mail: 574932286@qq.com
> Created Time: 2014年10月16日 星期四 13时37分05秒
一: 完成稀疏矩阵的建立i
二: 15:33 稀疏矩阵的加法
10,16 8:30 继续实现
10.19 15:07 继续
三: 10.20 00:44 稀疏矩阵得乘法
************************************************************************/
#include<stdlib.h>
#include<stdio.h>
#define MAXSIZE 100
typedef int ElementType;
typedef struct
{
int row;
int col;
ElementType value;
}Triple;
typedef struct
{
Triple data[MAXSIZE];
int rows,cols,nums;//非零起
}TSMatrix;
typedef TSMatrix * PtrTSMatrix;
PtrTSMatrix CreatMatrix( void );
void PrintMatrix( PtrTSMatrix Matrix );
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B );
PtrTSMatrix MinusMatrix( PtrTSMatrix A, PtrTSMatrix B );
PtrTSMatrix MultiMatrix( PtrTSMatrix A, PtrTSMatrix B );
/* Make a Matrix,use the triple array */
PtrTSMatrix CreatMatrix( void )
{
int count = 0;
PtrTSMatrix Matrix;
Matrix = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) );
if( Matrix == NULL )
{
printf("Not Space\n ");
exit( 0 );
}
printf("输入行与列\n");
scanf("%d%d",&Matrix->rows,&Matrix->cols);
printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)\n");
scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
while( Matrix->data[count].row != -1 )
{
count++;
scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 )
{
printf("未按行输出:\n");
getchar();
exit(0);
}//if
}//while
Matrix->nums = count;
return Matrix;
}/* CreatMatrix */
/* print the matrix Matrix by using matrix */
void PrintMatrix( PtrTSMatrix Matrix )
{
int i,j;
int count = 0;
for( i=0; i<Matrix->rows; i++ )
{
for( j=0; j<Matrix->cols; j++ )
{
if( count<Matrix->nums && i==Matrix->data[count].row-1 && j==Matrix->data[count].col-1 )
{
printf("%2d",Matrix->data[count].value);
count++;
}
else
{
printf("%2d",0);
}//if-else
}//for
printf("\n");
}//for
}/* PrintMatrix */
/* Plus A and B ,return C */
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
int i=0,j=0;//标记追逐 A B
PtrTSMatrix C;//存放和
if( A->rows!=B->rows || A->cols!=B->cols )
{
return NULL;
}
C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
C->rows = A->rows;
C->cols = A->cols;
C->nums = -1; //初始化
while( i<A->nums && j<B->nums )
{
if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
{
if( A->data[i].value+B->data[j].value != 0 )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value+B->data[j].value;
}
i++;
j++;//标记后移
}
else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
else
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}//if-else
}//while,
if( i == A->nums )
{
while( j < B->nums )
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}
}
else
{
while( i < A->nums )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
}//if-else
C->nums++;
return C;
}//AddMatrix
/* A mius B get C */
PtrTSMatrix MinusMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
int i=0,j=0;//标记追逐 A B
PtrTSMatrix C;//存放和
if( A->rows!=B->rows || A->cols!=B->cols )
{
return NULL;
}
C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
C->rows = A->rows;
C->cols = A->cols;
C->nums = -1; //初始化
while( i<A->nums && j<B->nums )
{
if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
{
if( A->data[i].value-B->data[j].value != 0 )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value-B->data[j].value;
}
i++;
j++;//标记后移
}
else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
else
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}//if-else
}//while,
if( i == A->nums )
{
while( j < B->nums )
{
C->nums++;
C->data[C->nums].col = B->data[j].col;
C->data[C->nums].row = B->data[j].row;
C->data[C->nums].value = B->data[j].value;
j++;
}
}
else
{
while( i < A->nums )
{
C->nums++;
C->data[C->nums].col = A->data[i].col;
C->data[C->nums].row = A->data[i].row;
C->data[C->nums].value = A->data[i].value;
i++;
}
}//if-else
C->nums++;
return C;
}/* MiinusMatrix */
/* get the answer of A multiply B */
PtrTSMatrix MultiMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
PtrTSMatrix C;
int num[MAXSIZE]={0};//第K行得非零元素得个数
int cpot[MAXSIZE]={0};//k行得第一个非零元素在三元组得位置
int i,j;
int count = 0;
int temp[MAXSIZE]={0};
if( A->cols != B->cols )
{
return NULL;
}//if ,输入检验
C = (PtrTSMatrix)malloc( sizeof(TSMatrix) );
C->rows = A->rows;
C->cols = B->cols;
for( i=0; i<B->nums; i++)
{
num[B->data[i].row-1]++;//m
if( i!=0 && B->data[i-1].row!=B->data[i].row )
{
cpot[B->data[i-1].row-1] = i;
}
}
for( i=0; i<A->nums; i++ )
{
if( i!=0 && A->data[i].row != A->data[i-1].row )
{
for( j=0; j < B->cols; j++ )
{
if( temp[j] != 0 )
{
C->data[count].row = A->data[i-1].row;
C->data[count].col = j+1;
C->data[count].value = temp[j];
count++;
}
}//for,赋值
for( j=0; j<B->cols; j++ )
{
temp[j] = 0;
}//for,初始化
}//if
for( j=0; j<num[A->data[i].col]; j++)
{
temp[ B->data[ cpot[A->data[i].col]+j ].col ] = + A->data[i].value*B->data[ cpot[A->data[i].col]+j ];//高度注意,自己写一下
}//for
}//for
return C;
}//MultiMatrix
int main(void)
{
PtrTSMatrix A,B,C,D,E;
A = CreatMatrix();
B = CreatMatrix();
C = AddMatrix( A, B );
D = MinusMatrix( A , B );
E = MultiMatrix( A, B );
printf("\n");
PrintMatrix( C );
printf("\n");
PrintMatrix( D );
printf("\n");
PrintMatrix( E );
return 0;
}