c语言稀疏矩阵运算器,数据结构:稀疏矩阵运算器

题目:设计一个程序,实现一个能进行稀疏矩阵基本运算的计算器。按照教科书《数据结构(C语言版)》(严蔚敏等)5.3.2节中描述的方法,以十字链表表示稀疏矩阵。

一、需求分析

稀疏矩阵是指那些多数元素为零的矩阵。利用“稀疏”特点进修学校储存和计算可以大大节省储存空间,提高计算效率。实现一个能进行稀疏矩阵基本运算的计算器。

以“带行逻辑链接信息”的三元组顺序表表示稀疏矩阵,实现两个矩阵相加、相减和相乘的运算。稀疏矩阵的输入形式采用三元组表示,而运算结果的矩阵则以通常的阵列形式列出。

测试数据

\left[ \begin{matrix} 10&0& 0 \\ 0&0&9 \\ -1&0&0 \\ \end{matrix}\right] + \left[ \begin{matrix} 0&0& 0 \\ 0&0&-1 \\ 1&0&-3 \\ \end{matrix}\right]= \left[ \begin{matrix} 10&0& 0 \\ 0&0&8 \\ 0&0&-3 \\ \end{matrix}\right]

\left[ \begin{matrix} 10&9 \\ 0&9 \\ -1&0 \\ \end{matrix}\right] - \left[ \begin{matrix} 0&0 \\ 0&-1 \\ 1&-3 \\ \end{matrix}\right]= \left[ \begin{matrix} 10&0 \\ 0&10 \\ -2&-3 \\ \end{matrix}\right]

\left[ \begin{matrix} 4&-3&0&0&1 \\ 0&0&0&8&0 \\ 0&0&1&0&0 \\ 0&0&0&0&0 \end{matrix}\right] \times \left[ \begin{matrix} 3&0&0 \\ 4&2&0 \\ 0&1&0 \\ 1&0&0 \\ 0&0&0 \end{matrix}\right] = \left[ \begin{matrix} 0&-6&0 \\ 8&0&0 \\ 0&1&0 \\ 0&0&0 \end{matrix}\right]

二、概要设计

1.数据结构

ADT SparseMatrix{

数据对象:D={ aij | i = 1,2,...,m; j = 1,2,...,n;

aij∈ElemSet, m和n分别为矩阵的行数和列数}

数据关系:R={Row,Col}

Row={|1≤i≤m,1≤j≤n-1 }

Col={|1≤i≤m-1,1≤j≤n }

基本操作:

CreateSMatrix(&M)

操作结果:创建稀疏矩阵M。

PrintSMatrix(M)

初始条件:稀疏矩阵M存在。

操作结果: 输出稀疏矩阵M。

AddSMatrix(M, N, &Q)

初始条件:稀疏矩阵M与N的行数和列数对应相等。

操作结果:求稀疏矩阵的和Q=M+N。

SubtSMatrix(M, N, &Q)

初始条件:稀疏矩阵M与N的行数和列数对应相等。

操作结果:求稀疏矩阵的差Q=M-N。

MultSMatrix(M, N, &Q)

初始条件:稀疏矩阵M的列数等于N的行数。

操作结果:求稀疏矩阵乘积Q=M*N。

}ADT SparseMatrix

2. 使用函数

(1)行逻辑链接的顺序表

int CreateSMatrix(RLSMatrix *M)

操作结果:创建稀疏矩阵

int PrintSMatrix(RLSMatrix M)

操作结果:打印稀疏矩阵

int AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)

操作结果:稀疏矩阵加法,Q=M+N

int SubSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)

操作结果:稀疏矩阵减法,Q=M-N

int MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)

操作结果:稀疏矩阵乘法,Q=M*N

(2)十字链表

int CreateSMatrix_OL(CrossList *M)

操作结果:创建稀疏矩阵

int PrintSMatrix_OL(CrossList M)

操作结果:打印稀疏矩阵

int AddSMatrix_OL(CrossList *A, CrossList *B)

操作结果:将稀疏矩阵B加到稀疏矩阵A上

int SubSMatrix_OL(CrossList *A, CrossList *B)

操作结果:在稀疏矩阵A上减去稀疏矩阵B

int MultSMatrix_OL(CrossList A, CrossList B, CrossList *C)

操作结果:稀疏矩阵乘法,C=A*B

三、详细设计

1. 数据储存结构

(1)行逻辑链接顺序表

#define MAXSIZE 400 // 最大非零元个数

#define MAXRC 20 // 最大行数和列数

typedef struct{

int i,j; // 该非零元的行下标和列下标

int e;

}Triple;

typedef struct{

Triple data[MAXSIZE+1]; // 非零元三元组表

int rpos[MAXRC+1]; // 各行第一个非零元位置表

int mu,nu,tu; // 矩阵行数、列数和非零元个数

}RLSMatrix;

(2)十字链表

#define MAXSIZE 400 // 最大非零元个数

#define MAXRC 20 // 最大行数和列数

typedef struct OLNode{

int i,j; // 该非零元的行和列下标

int e;

struct OLNode *right, *down; // 该非零元所在行表和列表的后继链域

}OLNode, *OLink;

typedef struct {

OLink *rhead, *chead; // 行和列链表头指针向量基址由CreateSMatrix分配

int mu, nu, tu; // 稀疏矩阵行数、列数和非零元个数

}CrossList;

2.基本功能实现

2.1行逻辑链接顺序表

(1)稀疏矩阵创建

分别读入矩阵行数、列数以及非零元个数,同时提示输入各个非零元位置和数值,对于输入的非零元判断是否合法,并根据行号和列号进行以行为主序的储存,最后计算各行首个非零元位置。

int CreateSMatrix(RLSMatrix *M){

if(M) free(M);

int m,n,t;

do{

printf("输入矩阵行数,列数和非零元数目,用空格隔开\n");

scanf("%d %d %d", &m, &n, &t);

if(m < 0 || n < 0 || t < 0 || t > m*n){

printf("参数错误 \n");

}

}while(m < 0 || n < 0 || t < 0 || t > m*n);

M->mu = m; M->nu = n; M->tu = t;

printf("请按行优先输入三元组\n");

int i,j,e,k;

int p,q;

for(k = 1; k <= t; k++){

do{

printf("输入第%d个非零元的行号 列号 值, 用空格隔开\n",k);

scanf("%d %d %d", &i, &j, &e);

if(i <= 0 || j <= 0 || i > m || j > n|| e==0){

printf("参数错误\n");

}

}while(i <= 0 || j <= 0 || i > m || j > n|| e==0);

for(p = 1; p <= k-1 && (i > M->data[p].i || (i == M->data[p].i && j > M->data[p].j)); p++); //找到三元组插入的位置

for(q = k-1;q >= p; q--) M->data[q+1] = M->data[q]; //行序大的三元组依次向后移动

M->data[p].i = i;

M->data[p].j = j;

M->data[p].e = e;

}

int row,x;

int num[MAXRC + 1];

for(row = 1; row <= M->mu; ++row) num[row] = 0;

for(x = 1; x <= M->tu; ++x) ++num[M->data[x].i]; // 每一行非零元个数

M->rpos[1] = 1;

for(row = 2; row<=M->mu; ++row) M->rpos[row] = M->rpos[row-1] + num[row-1]; // 各行首个非零元位置

return 1;

}

(2)稀疏矩阵加减法

加减法基本思路一致,这里以加法为例。找到M和N矩阵各行非零元素的起始和终末位置之后开始遍历,对列号相等和不等两种情况分别处理,并处理相加结果等于0的情况。

int AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q){

int arow;

int p,q,s = 1;

int tp,tq;

if(M.mu != N.mu || M.nu != N.nu) return 0;

Q->mu = M.mu; Q->nu = M.nu;

for(arow = 1; arow <= M.mu; ++arow){

Q->rpos[arow] = Q->tu + 1;

p = M.rpos[arow]; q = N.rpos[arow];

if(arow < M.mu){

tp = M.rpos[arow + 1];

tq = N.rpos[arow + 1];

}

else{

tp = M.tu + 1;

tq = N.tu + 1;

}

while(p < tp && q < tq){

if(M.data[p].j != N.data[q].j){ // 列号不等

if(M.data[p].j < N.data[q].j){

Q->data[s].i = arow;

Q->data[s].j = M.data[p].j;

Q->data[s].e = M.data[p].e;

s++; p++; Q->tu++;

}else{

Q->data[s].i = arow;

Q->data[s].j = N.data[q].j;

Q->data[s].e = N.data[q].e;

s++; q++; Q->tu++;

}

}else{ // 列号相等

if(M.data[p].e + N.data[q].e != 0){ // 结果非零

Q->data[s].i = arow;

Q->data[s].j = M.data[p].j;

Q->data[s].e = M.data[p].e + N.data[q].e;

s++; q++; p++; Q->tu++;

}else{q++; p++;}

}

}

while(p < tp){

Q->data[s].i = arow;

Q->data[s].j = M.data[p].j;

Q->data[s].e = M.data[p].e;

p++; s++; Q->tu++;

}

while(q < tq){

Q->data[s].i = arow;

Q->data[s].j = N.data[q].j;

Q->data[s].e = N.data[q].e;

q++; s++; Q->tu++;

}

}

return 1;

}

(3)稀疏矩阵乘法

对于M中每个元素M.data[p]找到N中所有满足条件M.data[p].j=N.data[q].i的元素N.data[q],求得M.data[p].e * N.data[q].e,对Q中元素设计累计和变量,初值为零,扫描数组M,求得相应元素乘积累加到适当的求累计和变量上。Q中元素行号与M中元素行号一致,又M中元素以M的行序为主序,因此对Q进行逐行处理,先求得累计和的中间结果(Q的一行),再压缩储存到Q.data中去。

int MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q){

// 求矩阵乘积Q=M×N,采用行逻辑链接储存表示

int arow,brow;

int p,q,t,tp;

int ccol;

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值