稀疏矩阵的三元组行逻辑链接的顺序表存储
三元组行逻辑链接顺序表存储结构: 采用三元组行逻辑链接存储稀疏矩阵的实例:
三元组行逻辑链接的顺序表存储表示 比三元组顺序表存储表示 增加 了 rpos 数组,用以存放各行的第一个非零元素在 data 数组中的位置。这样,就可以迅速地 找到某一行的元素。(创建稀疏矩阵输入非零元时,也要按行、列的顺序由小到大输入。)
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */
#include<stdarg.h> /* 标准头文件,提供宏va_start,va_arg和va_end, */
/* 用于存取变长参数表 */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
/* --------------------------- 稀疏矩阵的三元组行逻辑链接的顺序表存储表示 ------------------------------*/
#define MAXSIZE 100 /* 非零元个数的最大值 */
#define MAXRC 20 /* 最大行列数 */
typedef struct
{
int i, j; /* 行下标,列下标 */
ElemType e; /* 非零元素值 */
}Triple; /* 同c5-2.h */
typedef struct
{
Triple data[MAXSIZE + 1]; /* 非零元三元组表,data[0]未用 */
int rpos[MAXRC + 1]; /* 各行第一个非零元素的位置表,比c5-2.h增加的项 */
int mu, nu, tu; /* 矩阵的行数、列数和非零元个数 */
}RLSMatrix;
/* ------------------------------------------------------------------------------------------*/
/* --------------------------- 行逻辑链接稀疏矩阵的基本操作(8个) --------------------------*/
Status CreateSMatrix(RLSMatrix *M)
{ /* 创建稀疏矩阵M */
int i;
Triple T;
Status k;
printf("请输入矩阵的行数,列数,非零元素数:");
scanf_s("%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);
scanf_s("%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;
}
void DestroySMatrix(RLSMatrix *M)
{ /* 销毁稀疏矩阵M(使M为0行0列0个非零元素的矩阵) */
(*M).mu = 0;
(*M).nu = 0;
(*M).tu = 0;
}
void PrintSMatrix(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]);
}
void PrintSMatrix1(RLSMatrix M)
{ // 按矩阵形式输出M
int i, j, k = 1;
Triple *p = M.data;
p++; // p指向第1个非零元素
for (i = 1; i <= M.mu; i++)
{
for (j = 1; j <= M.nu; j++)
if (k <= M.tu&&p->i == i && p->j == j) // p指向非零元,且p所指元素为当前处理元素
{
printf("%3d", p->e); // 输出p所指元素的值
p++; // p指向下一个元素
k++; // 计数器+1
}
else // p所指元素不是当前处理元素
printf("%3d", 0); // 输出0
printf("\n");
}
}
Status CopySMatrix(RLSMatrix M, RLSMatrix *T)
{ /* 由稀疏矩阵M复制得到T */
*T = M;
return OK;
}
Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵的和Q=M+N */
int k, p, q;
if (M.mu != N.mu || M.nu != N.nu)
return ERROR;
(*Q).mu = M.mu;
(*Q).nu = M.nu;
(*Q).tu = 0;
M.rpos[M.mu + 1] = M.tu + 1; /* 为方便后面的while循环临时设置 */
N.rpos[N.mu + 1] = N.tu + 1;
for (k = 1; k <= M.mu; ++k) /* 对于每一行,k指示行号 */
{
(*Q).rpos[k] = (*Q).tu + 1;
p = M.rpos[k]; /* p指示M矩阵第k行当前元素的序号 */
q = N.rpos[k]; /* q指示N矩阵第k行当前元素的序号 */
while (p < M.rpos[k + 1] && q < N.rpos[k + 1])
{ /* M,N矩阵均有第k行元素未处理 */
if (M.data[p].j == N.data[q].j) /* M矩阵当前元素和N矩阵当前元素的列相同 */
{
(*Q).data[(*Q).tu + 1].e = M.data[p].e + N.data[q].e;
if ((*Q).data[(*Q).tu + 1].e != 0)
{
++(*Q).tu;
(*Q).data[(*Q).tu].i = k;
(*Q).data[(*Q).tu].j = M.data[p].j;
}
++p;
++q;
}
else if (M.data[p].j < N.data[q].j)
{ /* M矩阵当前元素的列<N矩阵当前元素的列 */
++(*Q).tu;
(*Q).data[(*Q).tu].e = M.data[p].e;
(*Q).data[(*Q).tu].i = k;
(*Q).data[(*Q).tu].j = M.data[p].j;
++p;
}
else /* M矩阵当前元素的列>N矩阵当前元素的列 */
{
++(*Q).tu;
(*Q).data[(*Q).tu].e = N.data[q].e;
(*Q).data[(*Q).tu].i = k;
(*Q).data[(*Q).tu].j = N.data[q].j;
++q;
}
}
while (p < M.rpos[k + 1]) /* M矩阵还有k行的元素未处理 */
{
++(*Q).tu;
(*Q).data[(*Q).tu].e = M.data[p].e;
(*Q).data[(*Q).tu].i = k;
(*Q).data[(*Q).tu].j = M.data[p].j;
++p;
}
while (q < N.rpos[k + 1]) /* N矩阵还有k行的元素未处理 */
{
++(*Q).tu;
(*Q).data[(*Q).tu].e = N.data[q].e;
(*Q).data[(*Q).tu].i = k;
(*Q).data[(*Q).tu].j = N.data[q].j;
++q;
}
}
return OK;
}
Status SubtSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵的差Q=M-N */
int i;
if (M.mu != N.mu || M.nu != N.nu)
return ERROR;
for (i = 1; i <= N.tu; ++i) /* 对于N的每一元素,其值乘以-1 */
N.data[i].e *= -1;
AddSMatrix(M, N, Q); /* Q=M+(-N) */
return OK;
}
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵乘积Q=M*N。算法5.3 */
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;
}
} /* 求得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];
}
}
}
return OK;
}
Status TransposeSMatrix(RLSMatrix M, RLSMatrix *T)
{ /* 求稀疏矩阵M的转置矩阵T */
int p, q, t, col, *num;
num = (int *)malloc((M.nu + 1) * sizeof(int));
(*T).mu = M.nu;
(*T).nu = M.mu;
(*T).tu = M.tu;
if ((*T).tu)
{
for (col = 1; col <= M.nu; ++col)
num[col] = 0; /* 设初值 */
for (t = 1; t <= M.tu; ++t) /* 求M中每一列非零元个数 */
++num[M.data[t].j];
(*T).rpos[1] = 1;
for (col = 2; col <= M.nu; ++col) /* 求M中第col中第一个非零元在(*T).data中的序号 */
(*T).rpos[col] = (*T).rpos[col - 1] + num[col - 1];
for (col = 1; col <= M.nu; ++col)
num[col] = (*T).rpos[col];
for (p = 1; p <= M.tu; ++p)
{
col = M.data[p].j;
q = num[col];
(*T).data[q].i = M.data[p].j;
(*T).data[q].j = M.data[p].i;
(*T).data[q].e = M.data[p].e;
++num[col];
}
}
free(num);
return OK;
}
/* ------------------------------------------------------------------------------------------*/
/* 检验以上操作的主程序 */
void main()
{
RLSMatrix A, B, C;
printf("创建矩阵A: ");
CreateSMatrix(&A);
PrintSMatrix1(A);
printf("由矩阵A复制矩阵B: ");
CopySMatrix(A, &B);
PrintSMatrix1(B);
DestroySMatrix(&B);
printf("销毁矩阵B后:\n");
PrintSMatrix1(B);
printf("创建矩阵B2:(与矩阵A的行、列数相同,行、列分别为%d,%d)\n", A.mu, A.nu);
CreateSMatrix(&B);
PrintSMatrix1(B);
printf("矩阵C1(A+B): ");
AddSMatrix(A, B, &C);
PrintSMatrix1(C);
DestroySMatrix(&C);
printf("矩阵C2(A-B): ");
SubtSMatrix(A, B, &C);
PrintSMatrix1(C);
DestroySMatrix(&C);
printf("矩阵C3(A的转置): ");
TransposeSMatrix(A, &C);
PrintSMatrix1(C);
DestroySMatrix(&A);
DestroySMatrix(&B);
DestroySMatrix(&C);
printf("创建矩阵A2: ");
CreateSMatrix(&A);
PrintSMatrix1(A);
printf("创建矩阵B3:(行数应与矩阵A2的列数相同=%d)\n", A.nu);
CreateSMatrix(&B);
PrintSMatrix1(B);
printf("矩阵C5(A*B): ");
MultSMatrix(A, B, &C);
PrintSMatrix1(C);
DestroySMatrix(&A);
DestroySMatrix(&B);
DestroySMatrix(&C);
}
运行结果: