目的:
编程实现稀疏矩阵的四则运算。
实现:
1. 稀疏矩阵的存储结构采用行逻辑表示的三元组
2.
#define MAXSIZE 12500 #define MAXRC 12500 typedef struct { int i, j; int e; }Triple; typedef struct { Triple data[MAXSIZE + 1]; int rpos[MAXRC + 1]; int mu, nu, tu; }RLSMatrix;
先通过创建mu nu tu的值再根据这些值采用循环输入得到data,之后再通过扫描确定rpos的值则可以完成创建。
通过三元组的形式将非零元对应的行列以及数值存储下来,再由稀疏矩阵结构存下矩阵的行数列数以及非零元个数,即可囊括稀疏矩阵的所有信息。这样就可以以三元组的形式把矩阵非零元素存储下来,节省了存储量的同时便于矩阵运算。
矩阵的加法
根据矩阵的相关知识,两个矩阵相加要求两个矩阵的行数,列数要相等。故需要设置判断是否满足矩阵相加的条件。若满足条件,则进行加法运算。根据矩阵加法法则,得到的新矩阵拥有与原来两矩阵相同的行数和列数,其元素数值则为两矩阵对应位置的元素值之和。矩阵的减法
和加法相同地根据三种情况采用三个循环处理对应的数据,只不过两个都有的情况结果要变为两者之差,N有M没有的情况要改为N元素的相反数,其余相同。则可以得到减法的算法。矩阵的乘法
根据矩阵乘法的理论,在满足M.nu==N.mu的情况下,新矩阵Q(i,j)的值即满足M(i,k)与N(k,j)的所有元素乘积之和。对于稀疏矩阵不需要对满足条件的每个元素都进行乘积,因为两者中若有一个为零则其乘积为零。所以只要在所有非零元中找到满足条件的配对进行相乘,在将乘积进行累加即可得到该位置的元素值。结合rpos可以高效地进行循环查找。
程序代码:
Matrix.h文件
#include<stdio.h> #define MAXSIZE 12500 #define MAXRC 12500 #define ERROR 0 #define OK 1 typedef struct { int i, j; int e; }Triple; typedef struct { Triple data[MAXSIZE + 1]; int rpos[MAXRC + 1]; int mu, nu, tu; }RLSMatrix; void CreateMatrix(RLSMatrix *M); void Initrpos(RLSMatrix *M); void Printrpos(RLSMatrix M); int Add(RLSMatrix M, RLSMatrix N, RLSMatrix *sum); int Minus(RLSMatrix M, RLSMatrix N, RLSMatrix *minus); int Multi(RLSMatrix M, RLSMatrix N, RLSMatrix *multi); void PrintMatrix(RLSMatrix M);
Matrix.c文件
#include<stdio.h> #include"Matrix.h" void CreateMatrix(RLSMatrix *M) { printf("请输入矩阵的行数,列数,和非零元个数\n"); scanf("%d%d%d", &M->mu, &M->nu, &M->tu); if (M->tu > (M->mu)*(M->nu)) { printf("该矩阵不存在!请重新输入!\n"); CreateMatrix(&M); } int s; for (s = 1; s <= M->tu; s++) { printf("请输入第%d非零元所在的行,列,及其数值\n", s); scanf("%d%d%d", &M->data[s].i, &M->data[s].j, &M->data[s].e); if (M->data[s].i < 0) { printf("行数须为正数!\n"); s -= 1; continue; } if(M->data[s].j < 0) { printf("列数须为正数!\n"); s -= 1; continue; } if(M->data[s].e==0){ printf("非零元不能为零!\n"); s -= 1; continue; } } } void Initrpos(RLSMatrix *M) { int i, j, tag, s; for (i = M->mu; i >= 1; i--) { tag = 0; for (j = 1; j <= M->nu; j++) { for (s = 1; s <= M->tu; s++) { if (M->data[s].i == i&&M->data[s].j == j) { M->rpos[i] = s; tag = 1; break; } } if (tag == 1)break; } if (i == M->mu&&tag == 0)M->rpos[i] = M->tu + 1; if (i != M->mu&&tag == 0)M->rpos[i] = M->rpos[i + 1]; } } void Printrpos(RLSMatrix M) { int i; printf("rpos\n"); for (i = 1; i <= M.mu; i++) { printf("第%d行:%d\n", i, M.rpos[i]); } } int Add(RLSMatrix M, RLSMatrix N, RLSMatrix *sum) { int m, n, c = 1; if (M.mu != N.mu || M.nu != N.nu) { printf("无法相加!\n"); return ERROR; } sum->mu = M.mu; sum->nu = M.nu; for (m = 1; m <= M.tu; m++) { for (n = 1; n <= N.tu; n++) { if (N.data[n].i == M.data[m].i&&N.data[n].j == M.data[m].j) { sum->data[c].i = N.data[n].i; sum->data[c].j = N.data[n].j; sum->data[c].e = M.data[m].e + N.data[n].e; c++; } } } for (m = 1; m <= M.tu; m++) { for (n = 1; n <= N.tu; n++) { if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) { break; } } if (n-1 == N.tu) { sum->data[c].i = M.data[m].i; sum->data[c].j = M.data[m].j; sum->data[c].e = M.data[m].e; c++; } } for (n = 1; n <= N.tu; n++) { for (m = 1; m <= M.tu; m++) { if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) { break; } } if (m-1 == M.tu) { sum->data[c].i = N.data[n].i; sum->data[c].j = N.data[n].j; sum->data[c].e = N.data[n].e; c++; } } sum->tu = c - 1; return OK; } int Minus(RLSMatrix M, RLSMatrix N, RLSMatrix *minus) { int m, n, c = 1; if (M.mu != N.mu || M.nu != N.nu) { printf("无法相减!\n"); return ERROR; } minus->mu = M.mu; minus->nu = M.nu; for (m = 1; m <= M.tu; m++) { for (n = 1; n <= N.tu; n++) { if (N.data[n].i == M.data[m].i&&N.data[n].j == M.data[m].j) { minus->data[c].i = N.data[n].i; minus->data[c].j = N.data[n].j; minus->data[c].e = M.data[m].e - N.data[n].e; c++; } } } for (m = 1; m <= M.tu; m++) { for (n = 1; n <= N.tu; n++) { if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) { break; } } if (n-1 == N.tu) { minus->data[c].i = M.data[m].i; minus->data[c].j = M.data[m].j; minus->data[c].e = M.data[m].e; c++; } } for (n = 1; n <= N.tu; n++) { for (m = 1; m <= M.tu; m++) { if (M.data[m].i == N.data[n].i && M.data[m].j == N.data[n].j) { break; } } if (m-1 == M.tu) { minus->data[c].i = N.data[n].i; minus->data[c].j = N.data[n].j; minus->data[c].e = -N.data[n].e; c++; } } minus->tu = c - 1; return OK; } int Multi(RLSMatrix M, RLSMatrix N, RLSMatrix *Q) { if (M.nu != N.mu)return ERROR; Q->mu = M.mu; Q->nu=N.nu; Q->tu = 0; int tp; int i; int p, brow; int q, ccol; if (M.tu*N.tu != 0) { int arow; int ctemp[12500]; for (arow = 1; arow <= M.mu; ++arow) { for (i = 1; i <= M.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; int t; if (brow < M.mu)t = N.rpos[brow + 1]; else { t = N.tu + 1; } for (q = N.rpos[brow]; q < t; ++q) { ccol = N.data