这道题也是上周就写了的,今天晚上赶紧发出来。题目如下:
看一下题目,就是三元组表稀疏矩阵的乘法,然后输出。
首先将矩阵每行的非0元个数记下来,那么矩阵每行第一个非0元在三元表的位置就是上一行非0元个数加上上一行首个非0元位置之和。这样就可以不用遍历三元表,就可以快速找到相应的三元组表元素。相乘时先将结果存入一个数组中,然后取其中非0元素存入新的三元组表。最后输出新三元组表即可。示例如下:
以下是我的实现:
#include <stdio.h> #include <stdlib.h> struct Triple { int ti; int tj; int value; }; struct tripleList { struct Triple T[2000]; int li; int lj; int ln; }; void createNewTripleList (struct tripleList *list); void getRowPot (struct tripleList *list,int rowPot[]); void clear (struct tripleList *list); void printTripleList (struct tripleList *list); void mul (struct tripleList *list1,struct tripleList *list2,struct tripleList *list3,int rowPot1[],int rowPot2[]); void run (); int main() { run (); return 0; } void run () { int rowPot1[2000]={0},rowPot2[2000]={0}; struct tripleList list1,list2,list3; createNewTripleList (&list1); createNewTripleList (&list2); getRowPot (&list1,rowPot1); getRowPot (&list2,rowPot2); mul (&list1,&list2,&list3,rowPot1,rowPot2); printTripleList (&list3); } void createNewTripleList (struct tripleList *list) { int i=0,a,b,c; scanf ("%d%d",&(list->li),&(list->lj)); while (1) { scanf ("%d%d%d",&a,&b,&c); if (a==0&&b==0&&c==0) { break; } list->T[i].ti=a-1; list->T[i].tj=b-1; list->T[i].value=c; i++; } list->ln=i; } void getRowPot (struct tripleList *list,int rowPot[]) { int n[2000]={0}; int i,pre1=0,pre2=0; for (i=0;i<=list->ln-1;i++) { (n[list->T[i].ti])++; } for (i=0;i<=list->li;i++) { rowPot[i]=pre1+pre2; pre1=n[i]; pre2=rowPot[i]; } } void printTripleList (struct tripleList *list) { int i; for (i=0;i<=list->ln-1;i++) { printf ("%d %d %d\n",list->T[i].ti+1,list->T[i].tj+1,list->T[i].value); } } void mul (struct tripleList *list1,struct tripleList *list2,struct tripleList *list3,int rowPot1[],int rowPot2[]) { int i,j,k,l,no,max,n,len1,len2,A[2000]={0}; list3->li=list1->li; list3->lj=list2->lj; for (i=0,n=0;i<=list1->li-1;i++) { len1=rowPot1[i+1]-1; for (j=rowPot1[i],max=0;j<=len1;j++) { len2=rowPot2[list1->T[j].tj+1]-1; for (k=rowPot2[list1->T[j].tj];k<=len2;k++) { no=list2->T[k].tj; A[no]+=list1->T[j].value*list2->T[k].value; max=no>max?no:max; } } for (l=0;l<=max;l++) { if (A[l]!=0) { list3->T[n].ti=list1->T[j-1].ti; list3->T[n].tj=l; list3->T[n].value=A[l]; ++n; A[l]=0; } } } list3->ln=n; }
以下是各函数的注释:
void createNewTripleList (struct tripleList *list) { int i=0,a,b,c; scanf ("%d%d",&(list->li),&(list->lj));//输入行数列数 while (1) { scanf ("%d%d%d",&a,&b,&c);//输入行 列 数据 if (a==0&&b==0&&c==0)//都为0时停止输入 { break; } list->T[i].ti=a-1;//赋值,因为题目输入的行列数据是从1开始的,这里将它转为以0开始,最后输出时在加上1 list->T[i].tj=b-1; list->T[i].value=c; i++; } list->ln=i;//得到三元组表元素个数 }
void getRowPot (struct tripleList *list,int rowPot[]) { int n[2000]={0}; int i,pre1=0,pre2=0; for (i=0;i<=list->ln-1;i++)//得到矩阵每行的非0元个数 { (n[list->T[i].ti])++; } for (i=0;i<=list->li;i++) { rowPot[i]=pre1+pre2;//本行第一个非0元素在三元组表中的位置,上一行的非0元个数加上上一行第一个非0元在三元组表中的位置 pre1=n[i]; pre2=rowPot[i]; } }
void mul (struct tripleList *list1,struct tripleList *list2,struct tripleList *list3,int rowPot1[],int rowPot2[]) { int i,j,k,l,no,max,n,len1,len2,A[2000]={0}; list3->li=list1->li;//得到行列 list3->lj=list2->lj; for (i=0,n=0;i<=list1->li-1;i++)//遍历第一个矩阵的行 { len1=rowPot1[i+1]-1;/得到这一行的所有非0元在三元组表的位置区间的右端 for (j=rowPot1[i],max=0;j<=len1;j++)//在这一行所有非0元在三元组表中的位置区间中遍历 { len2=rowPot2[list1->T[j].tj+1]-1;//得到第二个矩阵中列号与上一个for中的行号相等的所有非0元在三元组表的位置区间的最左端 for (k=rowPot2[list1->T[j].tj];k<=len2;k++)//在这一行所有非0元在三元组表中的位置区间遍历 { no=list2->T[k].tj; A[no]+=list1->T[j].value*list2->T[k].value;//在数组中添加相乘结果 max=no>max?no:max; } } for (l=0;l<=max;l++) { if (A[l]!=0)//将非0的结果存入新的三元组表中 { list3->T[n].ti=list1->T[j-1].ti; list3->T[n].tj=l; list3->T[n].value=A[l]; ++n; A[l]=0; } } } list3->ln=n;//得到新三元组表的元素个数 }
void printTripleList (struct tripleList *list) { int i; for (i=0;i<=list->ln-1;i++)//输出三元组表的所有元素 { printf ("%d %d %d\n",list->T[i].ti+1,list->T[i].tj+1,list->T[i].value); } }
void run () { int rowPot1[2000]={0},rowPot2[2000]={0}; struct tripleList list1,list2,list3; createNewTripleList (&list1);//输入两个三元组表 createNewTripleList (&list2); getRowPot (&list1,rowPot1);//得到它们的位置数组 getRowPot (&list2,rowPot2); mul (&list1,&list2,&list3,rowPot1,rowPot2);//相乘 printTripleList (&list3);//输出 }以上就是我的实现,希望给大家带来帮助。