三元組表示的稀疏矩陣的加法和乘法
阿新 • • 發佈:2019-02-10
#include <stdio.h> #include <stdlib.h> //函式結果狀態碼 #define OK 1 #define ERROR 0 #define OVERFLOW -1 //Status是函式的型別,其值是函式結果狀態程式碼 typedef int Status; // ----- 稀疏矩陣的三元組順序表儲存表示 ----- #define MAXSIZE 100 //假設非零元個數的最大值為100 #define MAXRC 100 typedef struct { int i,j; //非零元的行下標和列下標 int e; //非零元的值 }Triple; typedef struct { Triple data[MAXSIZE + 1]; //非零元三元組表,data[0]未用 int rpos[MAXRC + 1]; //各行的第一個非零元的位置表 int mu, nu, tu; //矩陣的行數、列數和非零元個數 }RLSMatrix; Status CreateSMatrix(RLSMatrix *M); //建立稀疏矩陣M,採用三元組儲存 Status PrintSMatrix(RLSMatrix M); //輸出稀疏矩陣M Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q); //求稀疏矩陣的和Q = M + N Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q); //求稀疏矩陣乘積Q = M ×N main() { RLSMatrix A, B, C;//稀疏矩陣A、B和C均以三元組表作為儲存結構,C存放A、B相加相乘的結果 //建立稀疏矩陣A、B printf("請輸入稀疏矩陣A\n"); CreateSMatrix(&A); printf("稀疏矩陣A為:\n"); PrintSMatrix(A); printf("\n\n"); printf("請輸入稀疏矩陣B\n"); CreateSMatrix(&B); printf("稀疏矩陣B為:\n"); PrintSMatrix(B); printf("\n\n"); //求稀疏矩陣的和C = A + B,並輸出相加結果矩陣C if(AddSMatrix(A, B, &C)) { printf("求疏矩陣的和C = A + B,並輸出相加結果矩陣C:\n"); PrintSMatrix(C); printf("\n"); } else printf("兩個矩陣行列數不完全相等,不是同類矩陣,不能相加。\n" ); //求稀疏矩陣乘積C = A ×B,並輸出相乘結果矩陣C if(MultSMatrix(A, B, &C)) { printf("稀疏矩陣乘積C = A ×B,並輸出相乘結果矩陣C:\n"); PrintSMatrix(C); printf("\n"); } else printf("稀疏矩陣A的列數和B的行數不相等,不能相乘。\n"); printf("\n"); //程式結束 system("pause"); return 0; } //建立稀疏矩陣M,採用三元組表儲存表示 Status CreateSMatrix(RLSMatrix *M) { int m, n, t, e; //行數m,列數n,非零元個數t和非零元值e int i, j, k, a, b; //中間變數 int num[MAXSIZE]; //每行非零元素個數 int flag [MAXSIZE][MAXSIZE]; //標記陣列:此位置是否已經有非零元素 for(i = 0; i < MAXSIZE; i++) //標記陣列的初始化 for(j = 0; j < MAXSIZE; j++) flag [i][j] = 0; //輸入M的行數、列數和非零元個數 do { printf("請分別輸入矩陣的行數、列數和非零元個數:\n"); printf("行數:"); scanf("%d", &m); printf("列數:"); scanf("%d", &n); printf("非零元的個數:"); scanf("%d", &t); if(m < 0 || n < 0 || t < 0 || t > m * n) printf("輸入的資料不符合要求!!!"); } while(m < 0 || n < 0 || t < 0 || t > m * n); M->mu = m, M->nu = n, M->tu = t;//儲存 //按行序輸入非零元 if(t == 0) return OK; for(k = 1; k <= t; k++) { do { printf("請輸入第%d個非零元(總共%d個)的行和列:\n", k, t); printf("對應行:"); scanf("%d", &i); printf("對應列:"); scanf("%d", &j); if(i <= 0 || i > m || j <= 0 || j > n) printf("輸入行或列不符合要求!!!\n"); if(flag [i][j] != 0) { printf("此處已存在非零元素!!!\n"); flag [i][j] = 2; } else flag [i][j] = 1; } while(i <= 0 || i > m || j <= 0 || j > n || flag [i][j] == 2);//檢測輸入是否合法 do { printf("非零元:"); scanf("%d", &e); if(e == 0) printf("輸入為0,請重新輸入!!!\n"); } while(e == 0); //檢測輸入是否合法 //按行序儲存資料 for(a = 1; a <= k-1 && (i > M->data[a].i || (i == M->data[a].i && j > M->data[a].j)); a++);//找到此三元組插入的位置 for(b = k-1; b >= a; b--) M->data[b+1] = M->data[b];//行序比它大的三元組依次向後移動 M->data[a].i = i, M->data[a].j = j, M->data[a].e = e;//儲存資料 } //求rpos if(M->tu) { for(i = 1; i <= M->mu; i++) num[i] = 0;//初始化 for(t = 1; t <= M->tu; t++) ++num[M->data[t].i];//求M中每一行含非零元素個數 //求rpos M->rpos[1] = 1; for(i = 2; i <= M->mu; i++) M->rpos[i] = M->rpos[i-1] + num[i-1]; } return OK; } //輸出稀疏矩陣M Status PrintSMatrix(RLSMatrix M) { int i, j, k;//中間變數 //輸出 for(i = 1, k = 0; i <= M.mu; i++) { for(j = 1; j <= M.nu; j++) { if(M.data[k+1].i == i && M.data[k+1].j == j) { printf("%d\t", M.data[k+1].e); k++; } else printf("0\t"); } printf("\n"); } printf("矩陣共有%d行%d列共%d個非零元素", M.mu, M.nu, M.tu); return OK; } //求稀疏矩陣的和Q = M + N Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q) { int i = 1, j = 1, k = 1; //中間變數 //檢查稀疏矩陣M和N的行數和列數是否對應相等 if(M.mu != N.mu || M.nu != N.nu) {//不完全相等,退出 return ERROR; } if(M.tu * N.tu == 0) return OK;//Q為零矩陣,直接返回 //初始化矩陣Q Q->mu = M.mu, Q->nu = M.nu, Q->tu = 0; //執行矩陣相加,按行的順序相加,分為四種情況 while(i <= M.tu && j <= N.tu)//M和N均不為空 { if((M.data[i].i == N.data[j].i && M.data[i].j < N.data[j].j) || (M.data[i].i < N.data[j].i))//矩陣M當前元素在矩陣N當前元素的前面 { Q->tu++;//非零元素增加 Q->data[k].i = M.data[i].i, Q->data[k].j = M.data[i].j, Q->data[k].e = M.data[i].e;//賦值 i++, k++;//移動指標 } else if((M.data[i].i == N.data[j].i && M.data[i].j > N.data[j].j) || (M.data[i].i > N.data[j].i))//矩陣M當前元素的在矩陣N當前元素的後面 { Q->tu++;//非零元素增加 Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = N.data[j].e;//賦值 j++, k++;//移動指標 } else if(M.data[i].e + N.data[j].e)//M和N當前結點對應且兩元素之和不為零 { Q->tu++;//非零元素增加 Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = M.data[i].e + N.data[j].e;//賦值 i++, j++, k++;//移動指標 } else //M和N當前結點對應且兩元素之和為零 { i++, j++;//指標向右移 } } //將矩陣M的剩餘元素插入矩陣Q while(i <= M.tu) { Q->tu++;//非零元素增加 Q->data[k].i = M.data[i].i, Q->data[k].j = M.data[i].j, Q->data[k].e = M.data[i].e;//賦值 i++, k++;//移動指標 } //將矩陣N的剩餘元素插入矩陣Q while(j <= N.tu) { Q->tu++;//非零元素增加 Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = N.data[j].e;//賦值 j++, k++;//移動指標 } return OK; } //求稀疏矩陣乘積Q = M ×N Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q) { int arow, brow, ccol, i, t, ctemp[N.nu+1], p, q, tp;//中間變數 //檢查稀疏矩陣M的列數和N的行數是否對應相等 if(M.nu != N.mu) return ERROR;//稀疏矩陣M的列數和N的行數不相等,不能相乘,退出 //初始化矩陣Q Q->mu = M.mu, Q->nu = N.nu, Q->tu = 0; //相乘 if(M.tu * N.tu != 0)//Q是非零矩陣 { for(arow = 1; arow <= M.mu; ++arow)//處理M的每一行 { for(i = 0; i <= N.nu; ++i) ctemp[i] = 0;//當前行各元素累加器清零 Q->rpos[arow] = Q->tu + 1; if(arow < M.mu) tp = M.rpos[arow + 1]; else tp = M.tu +1; for(p = M.rpos[arow]; p < tp; ++p)//對當前行中的每一個非零元 { brow = M.data[p].j; //找到對應元在N中的行號 if(brow < N.mu) t = N.rpos[brow+1]; else t = N.tu + 1; for(q = N.rpos[brow]; q < t; ++q) { ccol = N.data[q].j; //乘積元素在Q中列號 ctemp[ccol] += M.data[p].e * N.data[q].e; } }//求得Q中第crow( = 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]; } } } } return OK; }