36、矩陣(稀疏矩陣)的壓縮存儲(二)

上一節中我們討論的是稀疏矩陣的轉置,現在我們討論稀疏矩陣的相乘,相加,相減。如果預先知道不是稀疏矩陣,則用二維數組相乘法就可以了。如果是,則我們用來存儲矩陣的結構稱之爲行邏輯連接的順序表,就是加入一個行表來記錄稀疏矩陣中每行的非零元素在三元組表中的起始位置。

一、算法思想

在M.data和N.data中找到相應的各對元素進行相乘即可。此時矩陣的存儲結構是

         在此,我們引入rpos[row]用來指示矩陣N的第row行中第一個非零元在N.data中的序號,則rpos[row+1]-1指示矩陣的第row行中最後一個非零元在N.data中的序號。而最後一行中最後一個非零元在N.data的位置就是N.tu了。

     如上圖中,N的rpos值爲:

二、C語言描述

三、C語言實現

#include"stdio.h"

#include"stdlib.h"

#define MAXSIZE12500

#define MAXRC   100

#define OK 1 

#define ERROR -1

typedef int ElemType;

typedef intStatus;

typedef struct 

{

int i,j;

ElemType e;

}Triple;

typedef struct

{

Tripledata[MAXSIZE+1];

intrpos[MAXRC+1];//各行第一個非零元的位置表

int mu,nu,tu;   //矩陣行數,列數和非0元個數

}RLSMatrix;

intcpot[MAXSIZE+1],num[MAXSIZE+1];

StatusCreateSMatrix(RLSMatrix &M)

 { // 創建稀疏矩陣M

   int i;

   Triple T;

   Status k;

   printf("請輸入矩陣的行數,列數,非零元素數:(Separated by commas)\n");

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

   M.data[0].i=0; // 爲以下比較做準備

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

   {

     do

     {

       printf("請按行序順序輸入第%d個非零元素所在的行(1~%d),列(1~%d),元素值:",i,M.mu,M.nu);

       printf("the 3 num Separated bycommas\n");

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

       k=0;

      if(T.i<1||T.i>M.mu||T.j<1||T.j>M.nu) // 行、列超出範圍

         k=1;

      if(T.i<M.data[i-1].i||T.i==M.data[i-1].i&&T.j<=M.data[i-1].j)// 沒有按順序輸入非零元素

         k=1;  //&&優先級比||高

     }while(k); // 當輸入有誤,重新輸入

     M.data[i]=T;

   }

   for(i=1;i<=M.tu;i++) // 計算rpos[]

     if(M.data[i].i>M.data[i-1].i)

      for(T.i=0;T.i<M.data[i].i-M.data[i-1].i;T.i++)

         M.rpos[M.data[i].i-T.i]=i;

   for(i=M.data[M.tu].i+1;i<=M.mu;i++) // 給最後沒有非零元素的幾行賦值

     M.rpos[i]=M.tu+1;

   return OK;

 }//CreateSMatrix

voidDestroySMatrix(RLSMatrix &M)

 { // 銷燬稀疏矩陣M(使M爲0行0列0個非零元素的矩陣)

   M.mu=0;

   M.nu=0;

   M.tu=0;

 }//DestroySMatrix

voidPrintSMatrix(RLSMatrix M)

 { // 輸出稀疏矩陣M

   int i;

   printf("%d行%d列%d個非零元素。\n",M.mu,M.nu,M.tu);

   printf("行  列  元素值\n");

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

    printf("%2d%4d%8d\n",M.data[i].i,M.data[i].j,M.data[i].e);

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

     printf("第%d行的第一個非零元素是本矩陣第%d個元素\n",i,M.rpos[i]);

 }//PrintSMatrix

StatusMultSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q)

 { // 求稀疏矩陣乘積Q=M*N。

   int arow,brow,p,q,ccol,ctemp[MAXRC+1];

   if(M.nu!=N.mu) // 矩陣M的列數應和矩陣N的行數相等

     return ERROR;

   Q.mu=M.mu; // Q初始化

   Q.nu=N.nu;

   Q.tu=0;

   M.rpos[M.mu+1]=M.tu+1; // 爲方便後面的while循環臨時設置

   N.rpos[N.mu+1]=N.tu+1;

   if(M.tu*N.tu!=0) // M和N都是非零矩陣

   {

     for(arow=1;arow<=M.mu;++arow)

     { //從M的第一行開始,到最後一行,arow是M的當前行

       for(ccol=1;ccol<=Q.nu;++ccol)

         ctemp[ccol]=0; //Q的當前行的各列元素累加器清零

       Q.rpos[arow]=Q.tu+1; //Q當前行的第1個元素位於上1行最後1個元素之後

      for(p=M.rpos[arow];p<M.rpos[arow+1];++p)

       { // 對M當前行中每一個非零元

         brow=M.data[p].j; //找到對應元在N中的行號(M當前元的列號)

        for(q=N.rpos[brow];q<N.rpos[brow+1];++q)

         {

           ccol=N.data[q].j; //乘積元素在Q中列號

          ctemp[ccol]+=M.data[p].e*N.data[q].e;

         }//for

       } //求得Q中第arow行的非零元

       for(ccol=1;ccol<=Q.nu;++ccol) //壓縮存儲該行非零元

         if(ctemp[ccol])

         {

           if(++Q.tu>MAXSIZE)

             return ERROR;

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

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

           Q.data[Q.tu].e=ctemp[ccol];

         }//if

     }//for

   }//if

   return OK;

 }//MultSMatrix

int main()

{

RLSMatrix M,N,Q;

CreateSMatrix(M);

CreateSMatrix(N);

MultSMatrix(M,N,Q);

PrintSMatrix(Q);

DestroySMatrix(M);

DestroySMatrix(N);

DestroySMatrix(Q);

return OK;

}

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