//存储结构
//在十字链表中,稀疏矩阵的每一行用一个带表头结点的循环链表表示
//每一列也用一个带表头的循环链表表示,在这个结构中,除了表头结点外,每个节点都代表矩阵中的非零元素
//它由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矩阵的行号时相乘。

posted on 2011-07-07 23:17  liveshow021  阅读(967)  评论(0编辑  收藏  举报