#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; }
三元组表示的稀疏矩阵的加法和乘法
最新推荐文章于 2022-02-14 15:07:16 发布