實現稀疏矩陣相乘C/C++

實現稀疏矩陣相乘C/C++

1、問題描述:已知稀疏矩陣A(m1,n1)和B(m2,n2),求乘積C(m1,n2)。
A=|3 0 0  7|    B=|4  1|   C=|12 17|
     |0 0 0 -1|         |0  0|        |0    -2|
     |0 2 0  0|         |1 -1|        |0      0|
                             |0   2|
A、B、C的三元組表示法分別爲:
A
  i j v
1 1 1 2
2 1 4 7
3 2 4 -1
4 3 2 2
B
  i j v
1 1 1 4
2 1 2 1
3 3 1 1
4 3 2 -1
5 4 2 2
C
  i j v
1 1 1 12
2 1 2 17
3 2 2 -2
2、解決思路:由矩陣乘法規則可知C(i,j) = A(i,1)*B(1,j)+A(i,2)*B(2,j)+....+A(i,n)*B(n,j),即C(i,j)爲A的第i行與B的第j列非零元素乘積之和。設置累加器temp[B的列值]保存C矩陣每行的值,結束後將temp中的值賦給C矩陣。
3、定義數據結構:
3.1、稀疏矩陣中節點的定義:
//定義三元組表的節點
typedef struct{
 int i,j;
 int v;
}SPNode;
i,j爲行列值,v爲此位置的數值。
3.2、稀疏矩陣的定義:
//定義三元組表
typedef struct{
 int mu,nu,tu;
 SPNode data[SMAX];
}SPMatrix;
mu爲矩陣行數,nu爲矩陣列數,tu爲矩陣中非零元素的個數。
4、具體實現:
爲了便於B.data尋找第k行第一個非零元素,在此引入num和rpot兩個內容。num[k]表示矩陣B中第k行非零元素的個數;rpot[k]表示第k行的第一個非零元素在B.data中的位置。
rpot[1] = 0;
rpot[k] = rpot[k-1]+num[k-1];
矩陣B中的num與rpot的值
col 1 2 3 4
num[col] 2 0 2 0
rpot[col] 0 2 2 4
4.1、初始化。清理一些單元,準備按行順序存放乘積矩陣。
4.2、求B的num與rpot。
4.3、做矩陣的乘法。
5、代碼的具體實現:
/*
 *進行兩個稀疏矩陣之間的乘法
*/
#include<stdio.h>
#include<malloc.h>
#define SMAX 1024
//定義三元組表的節點
typedef struct{
 int i,j;
 int v;
}SPNode;
//定義三元組表
typedef struct{
 int mu,nu,tu;
 SPNode data[SMAX];
}SPMatrix;
//進行兩個稀疏矩陣之間的乘法,返回值爲乘積矩陣
SPMatrix * MulSMatrix(SPMatrix *A,SPMatrix *B){
  SPMatrix *C;
  int p,j,q,i,r,k,t;
  //用於結果的暫存
  int temp[B->nu+1];
  int num[B->mu+1],rpot[B->mu+1];
  C = (SPMatrix*)malloc(sizeof(SPMatrix));
  if(C==NULL){
    printf("申請內存空間失敗!\n");
    return NULL;
  }
  //A的列值與B的行值不相等時
  if(A->nu!=B->mu) return NULL;
  C->mu = A->mu;
  C->nu = B->nu;
  //當A或B中的非零元素爲0時
  if(A->tu*B->tu==0){
    C->tu = 0;
    return C;
  }
  //計算B矩陣中每行非0元素的個數
  for(i = 1;i<=B->mu;i++)
    num[i] = 0;
  for(i = 0;i<B->tu;i++)
    num[B->data[i].i]++;
  rpot[1] = 0;
  //計算B矩陣中每行首位非0元素的位置
  for(i = 2;i<=B->mu;i++)
    rpot[i] = rpot[i-1]+num[i-1];
   r = 0;//記錄當前C矩陣中非0元素的個數
   p = 0;//指示當前A矩陣中非零元素的位置
   //進行矩陣的乘積運算
   for(i = 1;i<=A->mu;i++){
       //將Cij的累加器初始化
        for(j = 1;j<=B->nu;j++)
            temp[j] = 0;
            //求Cij第i行的元素集合
      while(i==A->data[p].i){
        k = A->data[p].j;//獲取A矩陣中第p個非零元素的列值
      //確定B中的k行的非零元素在B.data中的下限位置
        if(k<B->mu) t = rpot[k+1];
        else t = B->tu;
        //將B中第k行的每一列非零元素與A中非零元素記錄到累加器中
        for(q = rpot[k];q<t;q++){
            j = B->data[q].j;
            temp[j] += A->data[p].v*B->data[q].v;
        }
       p++;
      }
      //將第i行的結果賦值給C矩陣
      for(j = 1;j<=B->nu;j++){
        if(temp[j]!=0){
            C->data[r] = {i,j,temp[j]};
            r++;
        }
      }
   }
   C->tu = r;
   return C;
}
int main(){
    SPMatrix *A,*B,*C;
    int i;
    A = (SPMatrix*)malloc(sizeof(SPMatrix));
    B = (SPMatrix*)malloc(sizeof(SPMatrix));
    printf("請輸入A矩陣的行列值與非零元素");
    scanf("%d %d %d",&A->mu,&A->nu,&A->tu);
    printf("請輸入A矩陣的非零元素值:\n");
    for(i = 0;i<A->tu;i++)
        scanf("%d %d %d",&A->data[i].i,&A->data[i].j,&A->data[i].v);
    printf("請輸入B矩陣的行列值與非零元素");
    scanf("%d %d %d",&B->mu,&B->nu,&B->tu);
    printf("請輸入B矩陣陣的非零元素值:\n");
    for(i = 0;i<B->tu;i++)
        scanf("%d %d %d",&B->data[i].i,&B->data[i].j,&B->data[i].v);
    C = MulSMatrix(A,B);
    printf("C->nu:%d,C->mu:%d,C->tu:%d\n",C->mu,C->nu,C->tu);
    for(i = 0;i<C->tu;i++)
        printf("i:%d,j:%d,v:%d\n",C->data[i].i,C->data[i].j,C->data[i].v);
    delete A,B,C;
 return 0;
}
5、算法的時間複雜度:
5.1、求num的時間複雜度爲:O(2*B->nu)
5.2、求rpot的時間複雜度爲:O(B->mu)
5.3、求temp的時間複雜度爲:O(A->mu*B->nu)
5.4、求C中所有元素的時間複雜度爲:O(A->tu*B->tu/B->mu)





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