您的位置:首页 > 其它

稀疏矩阵顺序存储的运算方法

2015-04-27 20:24 501 查看
这里说说稀疏矩阵用三元组顺序存储的的运算方法:
首先是三元组的数据结构类型:

const int maxn= 100;

typedef struct{
int i,j;//矩阵行标,列标
int e;//元素值
}Triple;

typedef struct{
Triple date[maxn +1];//非零三元组表
int mu;//行数
int nu;//列数
int tu;//非零元数
}RLSMatrix;


先说说乘法的思想,两矩阵可以做乘法的前提是a
[m]*b[j][k]

m=j;

a.tu*b.tu!=0;
=>if(a.nu== b.mu && a.tu*b.tu!=0){...}
  然后a矩阵的第i行与b矩阵的第j列相乘作为新矩阵的第i,元;
//nump[i]记录矩阵p第i行非零元的个数prpos[i]记录矩阵p第i行第一个非零元在三元组中的位置
//numq[i]记录矩阵q第i行非零元的个数qrpos[i]记录矩阵q第i行第一个非零元在三元组中的位置
RLSMatrix Multiplication(RLSMatrix &p,RLSMatrix &q){
if(p.nu==q.mu && 0!=p.tu*q.tu){
RLSMatrix v;
v.mu=p.mu;
v.nu=q.nu;
v.tu=1;

//初始化
int nump[maxn+1];
int numq[maxn+1];
int pqtemp[maxn+1];
int prpos[maxn+1];
int qrpos[maxn+1];
memset(nump,0,sizeof(nump));
memset(numq,0,sizeof(numq));

for(int g=1;g<=p.tu;g++)//p 每一行非零元的个数;
nump[p.date[g].i]+=1;
for(int f=1;f<=q.tu;f++)//q 每一行非零元的个数;
numq[q.date[f].i]+=1;
for(int k=0;k<=q.tu+1;k++)//q 每行非零元地址设为0
qrpos[k]=0;
for(int h=0;h<=p.tu+1;h++)//p 每行非零元地址设为0
prpos[h]=0;

prpos[1]=1;
qrpos[1]=1;
for(int l=2;l<=q.mu+1;l++)//p每行非零元地址
prpos[l]=prpos[l-1]+nump[l-1];
for(int t=2;t<=q.mu+1;t++)//q 每行非零元地址
qrpos[t]=qrpos[t-1]+numq[t-1];

for(int arow=1;arow<=p.mu;arow++){
int a=prpos[arow];
int b=prpos[arow+1];
memset(pqtemp,0,sizeof(pqtemp));
//a的第i行与b的第i行对应相乘,得到的值按b对应的列标一一存在pqtemp中
for(int tt=a;tt<b ;tt++ ){
int w=p.date[tt].j;
int aa=qrpos[w];
int bb=qrpos[w+1];
for(int nn=aa;nn<bb;nn++){
//pi,j*qj,?
pqtemp[q.date[nn].j]+=p.date[tt].e*q.date[nn].e;
}
}
//将pqtemp中的值逐个存入结果三元组中
for(int mm=1;mm<=q.nu;mm++){//压缩存储
if(pqtemp[mm]!=0){
v.date[v.tu].i=arow;
v.date[v.tu].j=mm;
v.date[v.tu].e=pqtemp[mm];
v.tu+=1;
}
}
}
v.tu--;
return v;
}
else{
cout<<"两矩阵不满足乘法的条件!!"<<endl;
exit(0);
}
}


稀疏矩阵的转置
//cpot[i]第i列的第一个非零元的位置
//num[i]第i列非零元的个数
RLSMatrix TransposeSmatrix(RLSMatrix &M){
//矩阵为非空
if(M.tu){
RLSMatrix p;
//转置后矩阵的行值为原矩阵的列值,非零元个数不变
p.tu=M.tu;
p.nu=M.mu;
p.mu=M.nu;
//辅助数组,num[i]第i列非零元个数
//cpot[i]第i列的第一个非零元的位置
int num[maxn+1];
int cpot[maxn+1];
memset(num,0,sizeof(num));
memset(cpot,0,sizeof(cpot));

//num[i]和cpot[i]的初始化
for(int i=1;i<=M.tu;i++)
num[M.date[i].j]++;
cpot[1]=1;
for(int i=2;i<=M.nu;i++)
cpot[i]=cpot[i-1]+num[i-1];

//逐个读取原矩阵,进行转置变化
for(int k=1;k<=M.tu;k++){
int f=M.date[k].j;
int t=cpot[f];
p.date[t].i=M.date[k].j;
p.date[t].j=M.date[k].i;
p.date[t].e=M.date[k].e;
cpot[f]++;
}//for
return p;
}//if
}


稀疏矩阵的加法
RLSMatrix Add(RLSMatrix &p, RLSMatrix &q){
if(p.nu==q.nu && p.mu==q.mu){
RLSMatrix v;
int f=1,t=1,temp=1;
v.nu=p.nu;
v.mu=p.mu;
v.tu=0;
while(f
aaf9
<=p.tu && t<=q.tu){
if(p.date[f].i==q.date[t].i && p.date[f].j==q.date[f].j){
if(0!=(p.date[f].e+q.date[f].e)){
v.date[temp].i=p.date[f].i;
v.date[temp].j=p.date[f].j;
v.date[temp].e=p.date[f].e+q.date[f].e;
temp++;v.tu++;
//cout<<p.date[f].e<<' '<<q.date[f].e<<' '<<v.date[f].e<<' '<<temp<<' '<<v.tu<<endl;
}//if
f++;t++;
continue ;
}//if
else{
if( (p.date[f].i>q.date[t].i) || (p.date[f].i==q.date[t].i && p.date[f].j>q.date[t].j) ){
v.date[temp].i=q.date[t].i;
v.date[temp].j=q.date[t].j;
v.date[temp].e=q.date[t].e;
temp++;
t++;v.tu++;//cout<<p.date[f].e<<' '<<q.date[f].e<<' '<<v.date[f].e<<' 'temp<<' '<<v.tu<<endl;
continue ;
}//if
else{
v.date[temp].i=p.date[f].i;
v.date[temp].j=p.date[f].j;
v.date[temp].e=p.date[f].e;
temp++;
f++;v.tu++;
continue;
}//else
}//else
}//while
//三元组p未被读完
while(f<=p.tu){
v.date[temp].i=p.date[f].i;
v.date[temp].j=p.date[f].j;
v.date[temp].e=p.date[f].e;
temp++;
v.tu++;
f++;
}
//三元组q未被读完
while(t<=q.tu){
v.date[temp].i=q.date[t].i;
v.date[temp].j=q.date[t].j;
v.date[temp].e=q.date[t].e;
temp++;
v.tu++;
t++;
}
return v;
}//if
else{
cout<<"矩阵大小不相等,不可相加!!"<<endl;
exit(0);
}
}
//减法与加法原理类似,这里省去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: