用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx

上传人:b****5 文档编号:6417448 上传时间:2023-01-06 格式:DOCX 页数:34 大小:25.81KB
下载 相关 举报
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx_第1页
第1页 / 共34页
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx_第2页
第2页 / 共34页
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx_第3页
第3页 / 共34页
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx_第4页
第4页 / 共34页
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx

《用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx》由会员分享,可在线阅读,更多相关《用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx(34页珍藏版)》请在冰豆网上搜索。

用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料.docx

用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料

#include

#include

#defineSize2501

#defineSize151

typedefstruct

{

inti;

intj;

inte;//非零元的值

}triple;//定义三元组

typedefstruct

{

tripledata[Size+1];//矩阵中的元素

introps[Size1+1];//rops[i]为第i行元素中的首非零元在data[]中的序号

intmu;//行数

intnu;//列数

inttu;//非零元数

}juzhen;//定义矩阵

typedefstructnode//定义十字链表元素

{

inti,j,e;

structnode*right,*down;//该非零元所在行表和列表的后继元素

}node,*link;

typedefstruct//定义十字链表对象结构体

{

link*rhead,*chead;//行和列的头指针

intm,n,t;//系数矩阵的行数,列数,和非零元素个数

}crosslist;

voidcreatecross(crosslist&M)//建立十字链表

{

inti,j,e,k;

node*p,*q;

printf("输入行,列和非零元数,空格隔开:

\n");

scanf("%d%d%d",&M.m,&M.n,&M.t);

M.rhead=(link*)malloc((M.m+1)*sizeof(link));//给行和列的头指针分配内存

M.chead=(link*)malloc((M.n+1)*sizeof(link));

for(k=1;k<=M.m;k++)//初始化行,列的头指针

M.rhead[k]=NULL;

for(k=1;k<=M.n;k++)

M.chead[k]=NULL;

printf("输入非零元的行,列和值,空格隔开:

\n");

for(k=1;k<=M.t;k++)//输入非零元

{

scanf("%d%d%d",&i,&j,&e);

p=(node*)malloc(sizeof(node));

p->i=i;

p->j=j;

p->e=e;

if(M.rhead[i]==NULL||M.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标

{

p->right=M.rhead[i];

M.rhead[i]=p;

}

else

{

for(q=M.rhead[i];(q->right)&&q->right->jright);//空循环找到第一个列标大于或等于插入元素列标的元素

p->right=q->right;

q->right=p;

}

if(M.chead[j]==NULL||(M.chead[j]->i>i))//插入元素所在列无非零元或首非零元的行标大于插入元素的行标

{

p->down=M.chead[j];

M.chead[j]=p;

}

else

{

for(q=M.chead[j];(q->down)&&q->down->idown);//空循环找到第一个行标大于或等于插入元素行标的元素

p->down=q->down;

q->down=p;

}

}

}

voidprintcross(crosslistA)//输出十字链表

{

if(A.m==0)

printf("十字链表为空!

\n");

else

{

printf("十字链表为:

\n");

inti,j;

for(i=1;i<=A.m;i++)

{

linkp=A.rhead[i];

for(j=1;j<=A.n;j++)

{

if((p)&&(j==p->j))

{

printf("%5d",p->e);

p=p->right;}

else

printf("%5d",0);

}

printf("\n");

}

}

printf("\n");

}

crosslistaddcross()

{

printf("十字链表加法:

\n");

crosslista,b;//创建两个十字链表对象,并初始化

createcross(a);

createcross(b);

node*pre,*h[51],*pa,*pb,*q;//定义辅助指针,pa,pb分别为a,b当前比较的元素,pre为pa的前驱元素

inti,j,k=0,m,n;//h[j]指向j列的当前插入位置

if(a.m!

=b.m||a.n!

=b.n)

printf("格式不对,不能相加!

\n");

else

{

for(i=1;i<=a.m;i++)

{

pa=a.rhead[i];

pb=b.rhead[i];

pre=NULL;

for(j=1;j<=a.n;j++)

h[j]=NULL;

while(pb)

{

linkp;

p=(node*)malloc(sizeof(node));//开辟新节点,存储b中取出的元素

p->i=pb->i;

p->j=pb->j;

p->e=pb->e;

if(pa==NULL||pa->j>pb->j)//当a此行已经检查完或者pb因该放在pa前面

{

if(pre==NULL)

a.rhead[p->i]=p;

else

pre->right=p;

p->right=pa;

pre=p;

if(h[p->j]==NULL)//当前插入位置下面无非零元

//因为是逐行处理,so,h[p->j],依次下移

//因此每次都是指向插入的位置

{

a.chead[p->j]=p;

p->down=NULL;

}

else

{

p->down=h[p->j]->down;

h[p->j]->down=p;

}

h[p->j]=p;//*******h[p->j]下移指向下次插入的位置

pb=pb->right;//pb指向该行下个元素

}

elseif((pa&&pa->jj))//只要移动pa的指针****先不加||(pb==NULL&&pa)

{

pre=pa;

h[pa->j]=pa;//移动h[],使其指向下次插入的位置

pa=pa->right;

}

elseif(pa->j==pb->j)

{

pa->e+=pb->e;

if(pa->e)//不为零

{

pre=pa;

h[pa->j]=pa;

pb=pb->right;//加

}

else//pa->e为零,删除节点

{

if(pre==NULL)

a.rhead[pa->i]=pa->right;

else

{

pre->right=pa->right;

}

p=pa;//p指向pa,用来在下面修改列指针

pa=pa->right;

if(h[p->j]==NULL)

a.chead[p->j]=p->down;

else

{

h[p->j]->down=p->down;

}

free(p);

pb=pb->right;

}

}

}

}

}

returna;

}

voidmultycross(crosslist&c)//十字链表乘法

{

node*p,*q,*u,*v,*p1,*p2;

crosslista,b;

link*r;

inti,j,k,e;

printf("十字链表乘法:

\n");

createcross(a);

createcross(b);

if(a.n!

=b.m)

printf("格式错误,不能相乘!

\n");

else

{

c.m=a.m;

c.n=b.n;

c.t=0;

c.rhead=(link*)malloc((a.m+1)*sizeof(link));//给行和列的头指针分配内存

c.chead=(link*)malloc((b.n+1)*sizeof(link));

for(k=1;k<=a.m;k++)//初始化行,列的头指针

c.rhead[k]=NULL;

for(k=1;k<=b.n;k++)

c.chead[k]=NULL;

r=(link*)malloc((b.n+1)*sizeof(link));

for(i=1;i<=a.m;i++)

{

u=(node*)malloc(sizeof(node));

u->e=0;

u->i=0;

u->j=0;

for(k=1;k<=b.n;k++)//初始化r[]

r[k]=u;

p1=p=a.rhead[i];

for(j=1;j<=b.n;j++)

{

p=p1;

q=b.chead[j];

v=(node*)malloc(sizeof(node));//初始化v,v为将插入c矩阵的元素

v->e=0;

v->i=i;

v->j=j;

while(p&&q)

{

if(p->j>q->i)

q=q->down;

elseif(p->ji)

p=p->right;

else

{

v->e+=p->e*q->e;

p=p->right;

q=q->down;

}

}

if(v->e)//如果不为零,则插入c矩阵中

{

//同建立十字链表

if(c.rhead[i]==NULL||c.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标

{

v->right=c.rhead[i];

c.rhead[i]=v;

}

else

{

for(p2=c.rhead[i];(p2->right)&&(p2->right->jright);//空循环找到第一个列标大于或等于插入元素列标的元素

v->right=p2->right;

p2->right=v;

}

if(c.chead[j]==NULL||c.chead[j]->i>i)//插入元素所在列无非零元或首非零元的行标大于插入元素的行标

{

v->down=c.chead[j];

c.chead[j]=v;

}

else

{

for(p2=c.chead[j];(p2->down)&&(p2->down->idown);//空循环找到第一个行标大于或等于插入元素行标的元素

v->down=p2->down;

p2->down=v;

}

}

}

}

}

}

voidcreate(juzhen&M)//创建稀疏矩阵

{

inti,t=0;

printf("输入矩阵行数和列数and非零元的个数,以空格隔开:

\n");

scanf("%d%d%d",&M.mu,&M.nu,&M.tu);

printf("输入矩阵非零元的行,列,和数值(中间空格隔开):

\n");

for(i=1;i<=M.tu;i++)

scanf("%d%d%d",&M.data[i].i,&M.data[i].j,&M.data[i].e);//输入三元组的元素

for(i=1;i<=Size1;i++)//初始化rops【】

M.rops[i]=0;

for(i=1,t=1;i<=M.mu;i++)//得到各行第一个元素的序号

{

M.rops[i]=t;

while(M.data[t].i<=i&&t<=M.tu)//遇到i行非零元,则t累加

t++;

}

}

voidadd(juzhenA,juzhenB,juzhen&C)//稀疏矩阵加法

{

intk=1,temp=0,k1=1,k2=1;//k1,k2,k分别控制A,B,C中非零元的序号变化

printf("稀疏矩阵加法:

\n");

create(A);

create(B);

if(A.mu!

=B.mu||A.nu!

=B.nu)

printf("格式不对,不能相加!

\n");

else

{

while(k1<=A.tu&&k2<=B.tu)//当A,B中的非零元都没用完

{

if(A.data[k1].i

C.data[k++]=A.data[k1++];

elseif(A.data[k1].i>B.data[k2].i)//同上

C.data[k++]=B.data[k2++];

else//data[k1],data[k2]行标相同

{

if(A.data[k1].j>B.data[k2].j)//data[k1]列标大于data[k2]列标,则把data[k2]的值赋给data[k]

C.data[k++]=B.data[k2++];

elseif(A.data[k1].j

C.data[k++]=A.data[k1++];

else//行,列标都相同

{

temp=0;

temp=A.data[k1].e+B.data[k2].e;

if(temp)//相加后不为零

{

C.data[k].i=A.data[k1].i;

C.data[k].j=A.data[k1].j;

C.data[k].e=temp;

k++;

}

k1++;

k2++;

}

}

}

while(k1<=A.tu)//B中非零元已用完,A中还有非零元

C.data[k++]=A.data[k1++];

while(k2<=B.tu)//A中非零元已用完,B中还有非零元

C.data[k++]=B.data[k2++];

C.mu=A.mu;//确定C的行列数和非零元个数

C.nu=A.nu;

C.tu=k-1;

}

}

voidprint(juzhenA)//输出稀疏矩阵

{

printf("\n矩阵为:

\n");

inti,j,k=1;

if(A.mu==0)

printf("矩阵为空!

\n");

elseif(A.tu==0)//矩阵元素为空

printf("零矩阵!

\n");

else

for(i=1;i<=A.mu;i++)//逐行输出

{

for(j=1;j<=A.nu;j++)

{

if(A.data[k].i==i&&A.data[k].j==j)//行和列分别对应相等则输出相应非零元,否则输出零

printf("%5d",A.data[k++].e);

else

printf("%5d",0);

}

printf("\n");//该行输出结束,空行输出下一行

}

printf("\n");

}

voidmulty(juzhenA,juzhenB,juzhen&C)//稀疏矩阵乘法

{

intarow,brow,ccol,temp[51],p,q,t,tp,i;//各变量代表含义见下面

printf("稀疏矩阵乘法:

\n");

create(A);

create(B);

if(A.nu!

=B.mu)

printf("格式错误,不能相乘!

\n");

else

{

C.mu=A.mu;//初始化c的行列及非零元个数

C.nu=B.nu;

C.tu=0;

if(A.nu!

=B.mu)

printf("A,B格式不对不能相乘!

\n");

else//

{

for(arow=1;arow<=A.mu;arow++)//arow为当前A矩阵的行标

{

for(i=0;i<51;i++)//初始化temp

temp[i]=0;

if(arow

tp=A.rops[arow+1];//tp为arow+1行的首非零元在data【】中的序号

else//arow为最后一行

tp=A.tu+1;

for(p=A.rops[arow];p

{

brow=A.data[p].j;//brow为与B矩阵中的相应行对应的A中当前元素的列标

if(brow

t=B.rops[brow+1];//t为brow+1行的首非零元在B中data【】中的序号

else//brow大小等于B.mu

t=B.tu+1;

for(q=B.rops[brow];q

{

ccol=B.data[q].j;//ccol:

data[p]*data[q]所得结果所在的列

temp[ccol]+=A.data[p].e*B.data[q].e;//temp【ccol】:

相乘所得的C矩阵中第arow行cool列元素的值

}

}

for(ccol=1;ccol<=B.nu;ccol++)//

if(temp[ccol])//temp【ccol】不为零,则把值赋到c中,c.tu加1。

{

C.data[++C.tu].e=temp[ccol];

C.data[C.tu].i=arow;

C.data[C.tu].j=ccol;

}

}

}

}

}

voidclear(juzhen&A)//清空稀疏矩阵

{

inti;

A.mu=0;

A.nu=0;

A.tu=0;

for(i=0;i

A.rops[i]=0;

for(i=0;i

{

A.data[i].i=0;

A.data[i].j=0;

A.data[i].e=0;

}

}

voidmain()

{

juzhenA,B,C,D;

crosslista,b,c,d;

lable:

printf("******************************************************************\n");

printf("请选择:

1、稀疏矩阵的加法,并输出结果,2、稀疏矩阵乘法,并输出结果\n");

printf("\n3、十字链表加法,并输出,4、十字链表乘法并输出,5、结束:

\n");

printf("******************************************************************\n");

intx;

scanf("%d",&x);

switch(x)

{

case1:

add(A,B,C);

print(C);

printf("\n");

gotolable;

case2:

multy(A,B,C);

print(C);

printf("\n");

gotolable;

case3:

a=addcross();

printcross(a);

printf("\n");

gotolable;

case4:

multycross(b);

printcross(b);

printf("\n");

gotolable;

case5:

break;

}

printf("\n");

}

/*

乘法测试数据:

矩阵原型:

4-300130024-60

00080*-420800

00100010=010

000070100000

000

456

114

12-3

151

248

331

4570

535

113

21-4

222

321

411

4520

111

121

131

141

15

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1