十字鏈表實現矩陣加法(C語言實現)

C語言實現用十字鏈表表示的稀疏矩陣的加法。
題目:編寫兩個稀疏矩陣相加(C=A+B)的算法,要求稀疏矩陣用十字鏈表表示。
思路:首先建立十字鏈表,生成A,B。然後實現加法(注意要考慮各種情況!!)。
一些說明:
A----矩陣A ,B----矩陣B,C----矩陣C
用p,q控制A的行列
用u,v控制B的行列


下面是程序的代碼,註釋很詳細,相信你們能夠看懂,看不懂的可以留言給我。

#include<stdio.h>
#include<malloc.h>
#define smax 45
typedef int datatype;
typedef struct lnode  //結構體和共用體的定義
{
 int i,j;
 struct lnode *cptr,*rptr;
 union
 {
  struct lnode *next;
  datatype v;
 }uval;
}link;
int flag=0;
//建立稀疏矩陣的函數,返回十字鏈表頭指針
link *creatlinkmat()
{
 link *p,*q,*head,*cp[smax];
 int i,j,k,m,n,t,s;
 datatype v;
 printf("輸入行、列,非零元素個數(m,n,t數字間用逗號分隔)");
 scanf("%d,%d,%d",&m,&n,&t);//輸入行、列,非零元素個數 
 if(m>n)s=m; else s=n;  
 head=(link *)malloc(sizeof(link));  //建立十字鏈表頭結點
 head->i=m;head->j=n;
 cp[0]=head;   //cp[]是指針數組,分別指向頭結點和行、列表頭結點
 for(i=1;i<=s;i++) //建立頭結點循環鏈表
 {
  p=(link *)malloc(sizeof(link));
  p->i=0;p->j=0;
  p->rptr=p;p->cptr=p;
  cp[i]=p; cp[i-1]->uval.next=p;
 } 
 cp[s]->uval.next=head; 
 for(k=1;k<=t;k++)
 {
  printf("/t 第%d個元素(行號i 列號j 值v,數字間用空格分隔):",k);
  scanf("%d%d%d",&i,&j,&v);
  p=(link *)malloc(sizeof(link));
  p->i=i;p->j=j;p->uval.v=v;
  q=cp[i];
  while((q->rptr!=cp[i])&&(q->rptr->j<j))
   q=q->rptr;
  p->rptr=q->rptr;
  q->rptr=p; 
  q=cp[j];
  while((q->cptr!=cp[j])&&(q->cptr->i<i))
   q=q->cptr;
  p->cptr=q->cptr;
  q->cptr=p;
 }
 return head;
}
//插入結點函數
void insert(int i,int j,int v,link *cp[])
{
 link *p,*q;
 p=(link *)malloc(sizeof(link));
 p->i=i;p->j=j;p->uval.v=v;
 //以下是經*p結點插入第i行鏈表中  
 q=cp[i];
 while((q->rptr!=cp[i])&&(q->rptr->j<j))
  q=q->rptr;//在第i行中找第一個列號大於j的結點*(q->rptr)
 //找不到時,*q是該行表上的尾結點
 p->rptr=q->rptr;
 q->rptr=p;//*p插入在*q之後
 //以下是將結點插入第j列鏈表中
 q=cp[j];//取第j列表頭結點
 while((q->cptr!=cp[j])&&(q->cptr->i<i))
  q=q->cptr ;//在第j行中找第一個列號大於i的結點*(q->cptr)
 //找不到時,*q是該行表上的尾結點
 p->cptr=q->cptr;
 q->cptr=p;//*p插入在*q之後
}
//輸出十字鏈表的函數
void print(link *A)
{
 link *p,*q,*r;//p是控制行q是控制列r是控制輸出的格式
 int k,col,t,row; 
 col=A->j;//矩陣A的列數
 printf("矩陣爲:/n");
 p=A->uval.next;//p指向第一個結點(不是頭結點)
 while(p!=A)
 {
  q=p->rptr;//p指向這以一行的一個值
  if(q==A->cptr)break;//如果行或列處理完了,跳出
  r=p;//r指向這一行的頭結點
  while(q!=p)
  {
   for(k=1;k<q->j-(r->j);k++)//輸出同一行上兩非零數據間的零
    printf("  0");
   printf("%3d",q->uval.v);//輸出那個非零值
   q=q->rptr;//q指向這一行的下一個元素
   r=r->rptr;//r指向q前面的一個非零元素 
  }
  k=r->j;//k的值是某一行的最後一個非零元的列數
  for(t=k;t<col;t++)//輸出一行上最後一個非零元后面的零
   printf("  0");
  printf("/n");
  p=p->uval.next;//p指向下一行
 }
}
link *add(link *a,link *b)
{
 link *p,*q,*u,*v,*r,*cp[smax],*c;//p,q控制十字鏈a的行列,u,v控制十字鏈b的行列
 int s,i;
 if(a->i!=b->i||a->j!=b->j)
 { flag=1;return NULL; }
 //建立c的表頭環鏈
 c=(link *)malloc(sizeof(link));
 c->i=a->i;c->j=a->j;
 if(c->i>c->j)s=c->i; else s=c->j;
 cp[0]=c;
 for(i=1;i<=s;i++)
 {
  r=(link *)malloc(sizeof(link));
  r->i=0;r->j=0;
  r->rptr=r;r->cptr=r;
  cp[i]=r;
  cp[i-1]->uval.next=r;
 }
 cp[s]->uval.next =c; 
  //矩陣相加
 p=a->uval.next;u=b->uval.next;
 while(p!=a&&u!=b)
 {
  q=p->rptr;v=u->rptr;
  if(q==p&&v!=u)//矩陣a中第p行爲空,矩陣b的第u行不爲空
   while(v!=u)//將b的行的都複製到和矩陣中
   {insert(v->i,v->j,v->uval.v,cp);v=v->rptr;}
  else if(v==u&&q!=p)//矩陣a中第p行不爲空,矩陣b的第u行爲空
   while(q!=p)
   {insert(q->i,q->j,q->uval.v,cp);q=q->rptr;}
  else if(q!=p&&v!=u)//矩陣b的第u行和矩陣a的第p行都不爲空
  {
   while(q!=p&&v!=u)
   {
    if(q->j<v->j)//如果a中有元素的列數小於b的,將a中的所有小於b的值都插到c中
    {insert(q->i,q->j,q->uval.v,cp);q=q->rptr;}
    else if(q->j>v->j)//如果b中有元素的列數小於a的,將a中的所有小於b的值都插到c中
    {insert(v->i,v->j,v->uval.v,cp);v=v->rptr;}
    else//a、b當前是在同一個位置,判斷加的和是否爲零,不爲零才做加法運算
    {if(q->uval.v+v->uval.v!=0)insert(q->i,q->j,(q->uval.v+v->uval.v),cp);
     q=q->rptr;v=v->rptr;
    }
   }
   if(q==p&&v!=u)//如果b未處理完,將b中未處理的值都插入到和矩陣中
    while(v!=u)
    {insert(v->i,v->j,v->uval.v,cp);v=v->rptr;}
   else if(v==u&&q!=p)//如果a未處理完,將a中未處理的值都插入到和矩陣中
     while(q!=p)
     {insert(q->i,q->j,q->uval.v,cp);q=q->rptr;}
   else; //都處理完了,什麼都不做
  }
  else ; //矩陣b的第u行和矩陣a的第p行都爲空,什麼都不做
   
  p=p->uval.next;u=u->uval.next;//a、b都指向下一行
 }
 return c;
}
//
void main()
{
 link *A,*B,*C;
 A=creatlinkmat();print(A);
 B=creatlinkmat();print(B);
 C=add(A,B);
 if(flag==1)printf("矩陣A、B不能相加!!");
 else printf("和矩陣C爲:/n");print(C); 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章