//----------------稀疏矩阵的三元组顺序存储表示-------------------
//按行序优先存储
#include <iostream>
#include <cassert>
using namespace std;
#define MAXSIZE 2000 //假设非零元个数的最大值为2000,动态分配更好一些,这里只是做个测验
typedef int ElemType;
typedef struct
{
int i; //行下标
int j; //列下标
ElemType val; //值
}Triple;
typedef struct
{
Triple data[MAXSIZE]; //非零元三元组表,动态分配更好一些,这里只是做个测验
int rows; //行数
int cols; //列数
int nzs; //非零(no-zero)元个数
}TSMatrix;
//创建稀疏矩阵
void CreateTSMatrix( TSMatrix& M )
{
M.nzs = 0;
M.rows = 0;
M.cols = 0;
cout << "输入矩阵的行数和列数:";
cin >> M.rows >> M.cols;
assert( M.rows > 0 && M.cols > 0 );
cout << "请按顺序输入一个" << M.rows << "行"
<< M.cols << "列的矩阵:" << endl;
for( int i = 0; i < M.rows; ++i )
{
for ( int j = 0; j < M.cols; ++j )
{
int val;
cin >> val;
if ( val != 0 )
{
M.data[M.nzs].i = i;
M.data[M.nzs].j = j;
M.data[M.nzs].val = val;
M.nzs++;
}
}
}
}
//打印该稀疏矩阵
/*
* 按照T.data中三元组的次序依次在M.data中找到相应的三元组进行转置。换句话说,就是
* 按矩阵M的列序进行转置。
*/
void PrintTSMatrix( const TSMatrix& M )
{
int k = 0;
for ( int i = 0; i < M.rows; ++i )
{
for ( int j = 0; j < M.cols; ++j )
{
if ( k < M.nzs && M.data[k].i == i && M.data[k].j == j )
{
cout << M.data[k].val << " ";
++k;
}
else
{
cout << 0 << " ";
}
}
cout << endl;
}
}
//求M的转置矩阵T
/*
* 按照T.data中三元组的次序依次在M.data中找到相应的三元组进行转置。
* 换句话说,按照矩阵M的列序来进行转置。
*/
void TransposeTSMatrix( const TSMatrix& M, TSMatrix& T )
{
T.cols = M.rows;
T.rows = M.cols;
T.nzs = M.nzs;
if ( M.nzs )
{
int cnt = 0;
for ( int col = 0; col < M.cols; ++col )
{
for ( int p = 0; p < M.nzs; ++p )
{
if ( col == M.data[p].j )
{
T.data[cnt].i = M.data[p].j;
T.data[cnt].j = M.data[p].i;
T.data[cnt].val = M.data[p].val;
++cnt;
}
}
}
}
}
/*
* 按照M.data中三元组的次序进行转置,并将转置后的三元组置入
* T中恰当的位置。如果能预先确定矩阵M中每一列地第一个非零元
* 在T.data中应有的位置,那么在对M.data中的三元组依次转置时,
* 便可直接放到T.data中恰当的位置上去。
*/
void TransposeTSMatrixEx( const TSMatrix& M, TSMatrix& T )
{
T.cols = M.rows;
T.rows = M.cols;
T.nzs = M.nzs;
if ( M.nzs )
{
int *pNum = new int[M.cols];//表示矩阵M中第col列中非零元素的个数
for ( int i = 0; i < M.cols; ++i )
{
*(pNum+i) = 0;
}
for ( int i = 0; i < M.nzs; ++i )
{
++( *(pNum + M.data[i].j ) );
}
int* pCpot = new int [M.cols ]; //指示M中第col列的第一个非零元素在T.data中的恰当位置
*(pCpot) = 0;
for ( int i = 1; i < M.cols; ++i )
{
*(pCpot + i) = *(pCpot+i-1) + *(pNum+i-1);
}
for ( int i = 0; i < M.nzs; ++i )
{
int col = M.data[i].j;
int q = *(pCpot + col);
T.data[q].i = M.data[i].j;
T.data[q].j = M.data[i].i;
T.data[q].val = M.data[i].val;
++( *(pCpot + col));
}
delete[] pNum;
delete[] pCpot;
}
}
//判断M[i][j]是否是非零,若非0,则用iIndex返回该元素在三元组表中
//的位置,否则iIndex为-1
bool IsNoZeroAtPos( const TSMatrix& M, int i, int j, int& iIndex )
{
for( int k = 0; k < M.nzs; ++k )
{
if ( M.data[k].i == i && M.data[k].j == j )
{
iIndex = k;
return true;//非0
}
}
iIndex = -1;
return false; //为0
}
//矩阵的相加,相减的操作与相加类似
//时间复杂度为O(rows*cols*nzs),算法非常不好
void AddTSMatrix( const TSMatrix& M, const TSMatrix& N, TSMatrix& Q )
{
assert( M.rows == N.rows && M.cols == N.cols );
if ( M.rows != N.rows || M.cols != N.cols )
{
Q.rows = 0;
Q.cols = 0;
return;
}
int p = 0;
Q.cols = M.cols;
Q.rows = M.rows;
Q.nzs = 0;
for ( int i = 0; i < Q.rows; ++i )
{
for ( int j = 0; j < Q.cols; ++j )
{
int iIndexM;
int iIndexN;
bool bIsNoZeroM = IsNoZeroAtPos( M, i, j, iIndexM );
bool bIsNoZeroN = IsNoZeroAtPos( N, i, j, iIndexN );
if ( bIsNoZeroM && bIsNoZeroN )//M[i][j]与N[i][j]均非0,相加
{
Q.data[p].i = i;
Q.data[p].j = j;
Q.data[p].val = M.data[iIndexM].val + N.data[iIndexN].val;
++p;
++(Q.nzs);
}
else if ( bIsNoZeroM && !bIsNoZeroN )
{
Q.data[p].i = i;
Q.data[p].j = j;
Q.data[p].val = M.data[iIndexM].val;
++p;
++(Q.nzs);
}
else if ( !bIsNoZeroM && bIsNoZeroN)
{
Q.data[p].i = i;
Q.data[p].j = j;
Q.data[p].val = N.data[iIndexN].val;
++p;
++(Q.nzs);
}
else
{
;
}
}
}
}
//稀疏矩阵的相乘,时间复杂度很高!!设计的不够好
void MultTSMatrix( const TSMatrix& M, const TSMatrix& N, TSMatrix& Q )
{
assert( M.cols == N.rows );
if ( M.cols != N.rows )
{
Q.rows = 0;
Q.cols = 0;
return;
}
int p = 0;
Q.rows = M.rows;
Q.cols = N.cols;
Q.nzs = 0;
//采用矩阵相乘的经典算法
for ( int i = 0; i < Q.rows; ++i )
{
for ( int j = 0; j < Q.cols; ++j )
{
int tol = 0;
for ( int k = 0; k < M.cols; ++k )
{
int iIndexM;
int iIndexN;
bool bIsNoZeroM = IsNoZeroAtPos( M, i, k, iIndexM );
bool bIsNoZeroN = IsNoZeroAtPos( N, k, j, iIndexN );
if ( bIsNoZeroM && bIsNoZeroN )//当两个都不为0时,才进行相乘
{
tol += M.data[iIndexM].val * N.data[iIndexN].val;
}
}
if ( 0 != tol )//若为0,则表明乘积结果为0
{
Q.data[p].i = i;
Q.data[p].j = j;
Q.data[p].val = tol;
++p;
++(Q.nzs);
}
}
}
}
int main( int argc, char** argv )
{
TSMatrix M;
CreateTSMatrix( M );
system("cls");
cout << "当前矩阵M:" << endl;
PrintTSMatrix( M );
cout << endl;
TSMatrix T;
TransposeTSMatrix( M, T );
cout << "第一种方法转置后的矩阵T:" << endl;
PrintTSMatrix( T );
cout << endl;
TransposeTSMatrixEx( M, T );
cout << "第二种方法转置后的矩阵T:" << endl;
PrintTSMatrix( T );
cout << endl;
TSMatrix Q;
AddTSMatrix( M, T, Q );
cout << "矩阵M和T相加的结果为:"<< endl;
PrintTSMatrix( Q );
cout << endl;
MultTSMatrix( M, T, Q );
cout << "矩阵M和T相乘的结果为:"<< endl;
PrintTSMatrix( Q );
cout << endl;
return 0;
}