//
// Created by dgm on 19-3-6.
//
#define MaxSize 10000
#define MaxRow 100
#define MaxCol 100
typedef int ElemType;
typedef int Status;
#include <iostream>
using namespace std;
typedef struct Triple{
int row,col;
ElemType e;
}Triple;
typedef struct {
Triple data[MaxSize+1];
int rpos[MaxRow+1];
int row_num,col_num,non_zero_num;
}TSMatrix;
Status TransposeSMatrix(TSMatrix M,TSMatrix&T) //普通转置
{
int q=1;
T.col_num=M.row_num; //行列对应相等
T.row_num=M.col_num;
for (int col=1;col<=M.col_num;col++) { //对于M的每一列
for (int elem = 1; elem <= M.non_zero_num; ++elem){
if(M.data[elem].col==col) //将M中所有属于此列的元素
{ //以从上到下的顺序
T.data[q].row=M.data[elem].col; //按照列复制到
T.data[q].col=M.data[elem].row; //T中相应行
T.data[q].e=M.data[elem].e;
q++; //定位到M中同一列的下一个元素
}
}
}
return 1;
}
Status FastTransposeSMatrix(TSMatrix M,TSMatrix&T) //快速转置
{
T.col_num=M.row_num;
T.row_num=M.col_num;
T.non_zero_num=M.non_zero_num;
int num[M.col_num];
int cpot[M.col_num]; //cpot记录的是竖着看M中第i列首非零元素的位置
//也就是横着看T中第i行首非零元素的位置
for (int i = 1; i < M.col_num; ++i)
num[i]=0;
for (int i = 1; i <= M.non_zero_num; ++i) ++num[M.data[i].col];
cpot[1]=1;
for (int i = 2; i <= M.col_num; ++i) cpot[i]=cpot[i-1]+num[i-1];
for (int i = 1; i <= M.non_zero_num; ++i) {
int col=M.data[i].col; //data[i]在T中的位置就是根据它在M中的列col,通过cpot[col]得到的
int q=cpot[col];
T.data[q].row=M.data[i].col;
T.data[q].col=M.data[i].row;
T.data[q].e=M.data[i].e;
++cpot[col];
}
return 1;
}
void GetRowHead(TSMatrix&M) //获得每一行首非零元素的位置
{ //每一行首非零元素位置=
M.rpos[1]=1; //上一行首非零元素的位置+上一行非零元素的个数
int num[M.row_num]; //保存在M.rpos中,rpos[i]就是第i行首非零元素的位置
for (int i = 1; i <= M.row_num; ++i) num[i]=0;
for (int i = 1; i <= M.non_zero_num; ++i) ++num[M.data[i].row];
for (int i = 2; i <= M.row_num; ++i)M.rpos[i]=M.rpos[i-1]+num[i-1];
}
Status MultSMtrix(TSMatrix M,TSMatrix N,TSMatrix&Q) //计算M*N,结果放在Q中
{
if(M.row_num!=N.col_num)return 0; //不满足矩阵相乘条件
GetRowHead(M); //初始化rpos[]
GetRowHead(N);
Q.row_num=M.row_num,Q.col_num=N.col_num; //初始化结果的行数列数
Q.non_zero_num=0;
if(M.non_zero_num*N.non_zero_num!=0){
int ctemp[N.col_num+1]; //后边用来保存M中的第i行与N中所有列相乘
int tp; //得到的Q的第i行
for (int row = 1; row <= M.row_num; ++row) {
for (int i = 0; i <= N.col_num+1; ++i) {
ctemp[i]=0; //求出Q中的每一行之后,记得把临时保存结果的数组清零
}
Q.rpos[row]=Q.non_zero_num+1; //进行到这个位置,说明上一行Q已经全部求出来了
//所以Q中目前元素总数+1就是当前行的首非零元素位置
if(row<M.row_num)tp=M.rpos[row+1];//确定每一行的结束位置
else
tp=M.non_zero_num+1;//最后一行就是元素总数+1
for (int i = M.rpos[row]; i < tp; ++i) {//对于M第row行中的第i个元素
auto brow=M.data[i].col; //N中与之相乘的元素的行位置是确定的
int t; //并且这个行等于M.data[i]的列
if (brow<N.row_num)t=N.rpos[brow+1];//确定N中这一行元素的结束位置
else
t=N.non_zero_num+1;
for (int j = N.rpos[brow]; j < t; ++j) {
ctemp[N.data[j].col]+=M.data[i].e*N.data[j].e;
}
//M中的一行与N相乘,得到的是Q中的一行元素,那么这一行元素怎么计算呢?
//可以用M中该行第一个元素(设位于第i1列)与N中第i1行所有元素相乘,得到一行元素
//用M中该行第二个元素(设位于第i2列)与N中第i2行所有元素相乘,得到一行元素
//…………………………
//用M中该行最后一个元素(设位于第in列)与N中第in行所有元素相乘,得到一行元素
//最后把这n行元素按列相加,就得到了Q中相应的行
}
for (int ccol = 1; ccol <= Q.col_num; ++ccol) {//每一行计算完之后
if(ctemp[ccol]){ //按列增加顺序存入Q
if(++Q.non_zero_num>MaxSize)exit(EOVERFLOW);
Q.data[Q.non_zero_num].row=row;
Q.data[Q.non_zero_num].col=ccol;
Q.data[Q.non_zero_num].e=ctemp[ccol];
}
}
}
}
return 1;
}
int main()
{
TSMatrix M;
M.non_zero_num=5;
M.col_num=3;
M.row_num=3;
M.data[1].row=1;
M.data[1].col=1;
M.data[1].e=1;
M.data[2].row=1;
M.data[2].col=2;
M.data[2].e=5;
M.data[3].row=2;
M.data[3].col=1;
M.data[3].e=2;
M.data[4].row=3;
M.data[4].col=1;
M.data[4].e=3;
M.data[5].row=3;
M.data[5].col=3;
M.data[5].e=4;
TSMatrix T;
TSMatrix Q;
FastTransposeSMatrix(M,T);
MultSMtrix(M,T,Q);
cout<<Q.non_zero_num<<endl;
for (int i = 1; i <= Q.non_zero_num; ++i) {
cout<<"("<<Q.data[i].row<<","<<Q.data[i].col<<","<<Q.data[i].e<<")"<<endl;
}
return 0;
}
矩阵转置和乘法
猜你喜欢
转载自blog.csdn.net/qq_37613112/article/details/88369519
今日推荐
周排行