您的位置:首页 > 其它

稀疏矩阵相乘

2011-07-07 23:17 253 查看
//存储结构
//在十字链表中,稀疏矩阵的每一行用一个带表头结点的循环链表表示
//每一列也用一个带表头的循环链表表示,在这个结构中,除了表头结点外,每个节点都代表矩阵中的非零元素
//它由5个域组成:行,列,数据,向下指针,向右指针

//结点结构和存储表示如下图:



fig1. 交叉矩阵结构
//行域 列域 值域
//向下指针 向右指针

//为了使所有结点的存储结构一致,规定表头结点的结构与非零元素结点完全一致,只是将其行域和列域置为零
//由于每一行链表的表头与每一列链表的表头的行域和列域值均为零,故这两组表头结点可以公用
//即同行号、同列号的行头和列头共存储在一个结点之中,只是将其逻辑分开,起到共享资源的效果
//由此,得到稀疏矩阵的十字链表表示的结点总数等于非零元素个数+行头、列头+总表头

//由于十字链表表示的稀疏矩阵中,元素在稀疏矩阵中的具体位置不像二组数组矩阵那样,可以由矩阵元素的下标来对应相乘
//在稀疏矩阵的存储中,是通过行、列的链式交叉存储来实现的,零元素在矩阵中没有存储
//所以矩阵A的行和矩阵B的列在相乘的时候,要求寻找对应元素才能相乘,在元素相乘并移动指针的过程中
//当矩阵A的某行和矩阵B的某列相乘时,A矩阵X行中元素的列号col和B矩阵Y列中元素的行号row相同时才能相乘

//程序代码如下:

#include<stdio.h>
#include<iostream.h>
#include"head.h"

matrixType *crosslink()
{
int m,n,t,s,i,r,c,v;
matrixType *h[MAXSIZE],*p,*q;
cout<<"行数m,列数n,非零元素个数t:"<<endl;

cin>>m>>n>>t;
p=new matrixType;
p->row=m;
p->col=n;
h[0]=p;
s=m>n?m:n;
for(i=1;i<=s;i++)
{
p=new matrixType;
p->row=p->col=0;
p->right=p->down=p;
h[i]=p;
h[i-1]->tag.next=p;
}
h[s]->tag.next=h[0];

for(i=1;i<=t;i++)
{
cout<<"第"<<i<<"个元素(行号r,列号c,值v):"<<endl;
cin>>r>>c>>v;
p=new matrixType;
p->row=r;
p->col=c;
p->tag.val=v;
q=h[r];
while(q->right!=h[r]&&q->right->col<c)
q=q->right;
p->right=q->right;
q->right=p;
q=h[c];
while(q->down!=h[c]&&q->down->row<r)
q=q->down;
p->down=q->down;
q->down=p;
}

return (h[0]);

}

void dispcrosslink(matrixType *hm)
{
matrixType *p,*q;
cout<<"按行表输出矩阵元素:"<<endl;
cout<<"row="<<hm->row;
cout<<"\tcol="<<hm->col<<endl;
p=hm->tag.next;
while(p!=hm)
{
q=p->right;
while(q!=p)
{
cout<<" "<<q->row<<" "<<q->col<<" "<<q->tag.val<<endl;
q=q->right;
}
p=p->tag.next;
}
}

matrixType *multiply(matrixType *hm1,matrixType *hm2)
{
int sum,i,j,s,k;
matrixType *p1,*p2,*p,*q1,*q2,*q,*h[MAXSIZE];
s=hm1->row>hm2->col?hm1->row:hm2->col;
p=new matrixType;
p->row=hm1->row;
p->col=hm2->col;
h[0]=p;
for(i=1;i<=s;i++)
{
p=new matrixType;
p->row=p->col=0;
p->right=p->down=p;
h[i]=p;
h[i-1]->tag.next=p;
}
h[s]->tag.next=h[0];

p1=hm1->tag.next;
for(i=1;i<=hm1->row;i++)
{
p2=hm2->tag.next;
for(j=1;j<=hm2->col;j++)
{
sum=0;
q1=p1->right;
q2=p2->down;

for(k=1;k<=hm2->row;k++)
{
if(q1==p1||q2==p2) break;

if(q1->col==q2->row)
{
sum+=q1->tag.val*q2->tag.val;
q1=q1->right;
q2=q2->down;
}
else if(q1->col>q2->row)
{
q2=q2->down;
}
else
{
q1=q1->right;
}
}

if(sum!=0)
{
p=new matrixType;
p->row=i;
p->col=j;
p->tag.val=sum;
q=h[i];
while(q->right!=h[i])
q=q->right;
p->right=h[i];
q->right=p;
q=h[j];
while(q->down!=h[j])
q=q->down;
p->down=h[j];
q->down=p;
}

p2=p2->tag.next;
}
p1=p1->tag.next;
}

return (h[0]);
}

int main()
{
matrixType *hm1,*hm2,*hm3;
hm1=crosslink();
dispcrosslink(hm1);
hm2=crosslink();
dispcrosslink(hm2);
if(hm1->col!=hm2->row)
cout<<"若A矩阵的列不等于B矩阵的行,则两矩阵不能相乘!"<<endl;
else
{
hm3=multiply(hm1,hm2);
cout<<"相乘后的矩阵为:"<<endl;
dispcrosslink(hm3);
}

system("PAUSE");
return 0;
}

//head.h
#define MAXSIZE 10

typedef struct linknode
{
int row,col;
struct linknode *right,*down;
union
{
int val;
struct linknode *next;
}tag;
}matrixType;

此算法主体思想来源于网上,但原程序不能运算,稍加更改,并做了一些优化,主要还是阐述两稀疏矩阵相乘,定义数据结构以及在A矩阵的列号等于B矩阵的行号时相乘。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: