题目:设计一个程序,实现一个能进行稀疏矩阵基本运算的计算器。按照教科书《数据结构(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;

int ctemp[MAXRC + 1];

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

Q->mu = M.mu; Q->nu = N.nu; Q->tu = 0; // Q初始化

if(M.tu * N.tu != 0){ // Q是非零矩阵

for(arow = 1; arow <= M.mu; ++arow){ // 处理M的每一行

for(int i = 1; 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

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

ccol = N.data[q].j; // 乘积元素在Q中的列号

ctemp[ccol] += M.data[p].e * N.data[q].e;

}// for q

}// 求得Q中第crow(=arow)行的非零元

for(ccol = 1; ccol <= Q->nu; ++ccol){ //压缩储存改行非零元

if(ctemp[ccol]){

if(++Q->tu > MAXSIZE) return 0;

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

Q->data[Q->tu].j = ccol;

Q->data[Q->tu].e = ctemp[ccol];

}// if

} // for ccol

}// for arow

}// if

return 1;

}// MultSMatrix

(4)稀疏矩阵输出

通过双重循环,打印稀疏矩阵中非零元和零元素

int PrintSMatrix(RLSMatrix M){

int row,col,t = 1;

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

for(col = 1; col <= M.nu; col++){

if(M.data[t].i == row && M.data[t].j == col){

printf("%d\t",M.data[t].e);

t++;

}else{

printf("0\t");

}

}

printf("\n");

}

return 1;

}

2.2十字链表

(1)稀疏矩阵创建

读入矩阵行数、列数和非零元个数,同时提示输入各个非零元位置和数值,对于输入的非零元判断是否合法,生成结点并完成在行链表和列链表中的插入。

int CreateSMatrix_OL(CrossList *M){

if(M) free(M);

int c;

int m,n,t;

int i,j,k,e;

OLink p,q;

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;

if(!(M->rhead = (OLink*)malloc((m+1)*sizeof(OLink)))) exit(-2);

if(!(M->chead = (OLink*)malloc((n+1)*sizeof(OLink)))) exit(-2);

for(c = 1; c <= M->mu; c++) M->rhead[c]=NULL; // 初始化行列头指针向量

for(c = 1; c <= M->nu; c++) M->chead[c]=NULL;

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);

if(!(p = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p->i = i; p->j = j; p ->e = e; // 生成结点

if(M->rhead[i] == NULL || M->rhead[i]->j > j){

p->right = M->rhead[i];

M->rhead[i] = p;

}else{ // 寻找行表中的插入位置

for(q = M->rhead[i]; (q->right) && (q->right->j < j); q = q->right);

p->right = q->right;

q->right = p;

} // 完成行插入

if(M->chead[j] == NULL || M->chead[j]->i > i){ // 寻找列表中的插入位置

p->down = M->chead[j];

M->chead[j] = p;

}else{

for(q = M->chead[j]; (q->down) && (q->down->i < i); q = q->down);

p->down = q->down;

q->down = p;

} // 完成列插入

}

return 1;

}

(2)稀疏矩阵加减法

加减法基本思路一致,这里以加法为例。

非空指针pa和pb分别指向矩阵A,B中行值相同的两个结点,pa==NULL表明矩阵A在改行没有非零元,分为以下四种情况:

若pa==NULL或pa->j>pb->i,则需要在A矩阵的链表中插入一个值为bij的结点,此时,需要改变同一行中前一结点的right域值,以及同一列中前一结点的down域值。

若pa->jj,则将pa指针向右推进一步

若pa->j==pb->j,且pa->e+pb->e!=0,则只要将aij+bij的值送到pa所指结点的e域即可,其他所有域的值都不变

若pa->j==pb->j,且pa->e+pb->e==0,则需要在A矩阵链表中删除pa所指结点,此时需要改变同一行中前一结点的right域值以及同一列前一结点的down阈值。

为了便于插入和删除节点,还需要设置一些辅助指针。其一是在A的行链表上设pre指针,指示pa所指结点的前驱结点;其二是在A的每一列的链表上设一个指针hl[j],其初值和列链表的头指针相同,即hl[j]=chead[j]

int AddSMatrix_OL(CrossList *A, CrossList *B){

OLink pa, pb, pre, p, hl[MAXRC + 1];

int i, j;

if(A->mu != B->mu || A->nu != B->nu) return 0;

for(j = 1; j <= A->nu; j++) hl[j] = A->chead[j];

for(i = 1; i <= A->mu; i++){

pa = A->rhead[i]; pb = B->rhead[i]; pre = NULL;

while(pb){

if(!(p = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p->i = pb->i; p->j = pb->j; p->e = pb->e;

if(pa == NULL || pa->j > pb->j){ // 在A中插入pb所指结点的复制结点p

if(pre == NULL) A->rhead[p->i] = p;

else{pre->right = p; }

p->right = pa;

pre = p;

if(A->chead[p->j] == NULL || A->chead[p->j]->i > p->i){

p->down = A->chead[p->j];

A->chead[p->j] = p;

}else{ // 在hl[p->j]中找到新结点的前驱,插入结点

p->down = hl[p->j]->down;

hl[p->j]->down = p;

}

hl[p->j] = p;

pb = pb->right;

A->tu++;

}else if(pa && pa->j < pb->j){ // pa指向本行下一个非零结点

pre = pa;

pa = pa->right;

}else if(pa->j == pb->j){ // 加和

pa->e += pb->e;

if(pa->e == 0){ // 加和为0,删除结点,修改行表和列表相应指针

if(pre == NULL) A->rhead[pa->i] = pa->right;

else{pre->right = pa->right; }

p = pa; pa = pa->right;

if(A->chead[p->j] == p) A->chead[p->j] = hl[p->j] = p->down;

else{hl[p->j]->down = p->down; }

free(p);

pb = pb->right;

A->tu--;

}else{pre = pa; pa = pa->right; pb = pb->right; }

}

}

}

return 1;

}

(3)稀疏矩阵乘法

对于C中i行j列的元素,分别使p指向A中i行链表头指针,q指向B中j列链表头指针,累加和e置为零。p,q不为空时,

当p->j > q->i,q指针下移

当p->j < q->i,p指针右移

当p->j == q->i,对乘积累计求和,并移动指针

累加器e不为0时,则在矩阵C行列链表中插入节点p1,设置cpre和rpre分别指示行列链表中p1的前驱结点。

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

int i, j, e;

OLink p, q, p1, rpre, cpre;

if(A.nu != B.mu) return 0;

C->mu = A.mu; C->nu = B.nu; C->tu = 0; // 初始化矩阵C

if(!(C->rhead = (OLink*)malloc((C->mu+1)*sizeof(OLink)))) exit(-2);

if(!(C->chead = (OLink*)malloc((C->nu+1)*sizeof(OLink)))) exit(-2);

for(i = 1; i <= C->mu; i++) C->rhead[i] = NULL;

for(j = 1; j <= C->nu; j++) C->chead[j] = NULL;

for(i = 1; i <= C->mu; i++){

for(j = 1; j <= C->nu; j++){

p = A.rhead[i]; q = B.chead[j]; e = 0; // p,q分别指向A中该行链表头指针,B中该列链表头指针

while(p && q){

if(p->j > q->i){

q = q->down;

}else if(p->j < q->i){

p = p->right;

}else{

e += p->e * q->e; // 乘积累加

q = q->down;

p = p->right;

}

}

if(e){ // 累加不为0

C->tu++;

if(!(p1 = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p1->i = i; p1->j = j; p1->e = e;

p1->right = NULL; p1->down = NULL;

// 行插入

if(C->rhead[i] == NULL) {C->rhead[i] = p1; rpre = p1;}

else{rpre->right = p1; rpre = p1; }

// 列插入

if(C->chead[j] == NULL) {C->chead[j] = p1; cpre = p1;}

else{cpre->down = p1; cpre = p1; }

}

}

}

return 1;

}

(4)稀疏矩阵输出

通过双重循环,打印稀疏矩阵中非零元和零元素

int PrintSMatrix_OL(CrossList M){

OLink p;

int row,col;

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

if(M.rhead[row]){

p = M.rhead[row];

for(col = 1; col <= M.nu; col++){

if(p->i == row && p->j == col && p != NULL){

printf("%d\t",p->e);

if(p->right) p = p->right;

}else{printf("0\t");}

}

}else{for(col = 1; col <= M.nu; col++) printf("0\t");}

printf("\n");

}

return 1;

}

4.主程序

通过读入操作序号来进行相应操作,在满足操作对应条件下进行相应操作,并打印结果,两种储存方式下主程序结构基本一致,只是运算时调用函数不同。

int main(){

int num;

CrossList M, N, Q;

do{

printf("操作:1.矩阵相加 2.矩阵相减 3.矩阵相乘 4.退出\n");

scanf("%d",&num);

if(num == 1 || num == 2 || num == 3){

printf("请输入矩阵1\n");

CreateSMatrix_OL(&M);

printf("请输入矩阵2\n");

CreateSMatrix_OL(&N);

printf("两矩阵为:\n");

PrintSMatrix_OL(M);

printf("\n");

PrintSMatrix_OL(N);

switch(num){

case 1:

{

if(AddSMatrix_OL(&M, &N)){

printf("结果:\n");

PrintSMatrix_OL(M);

}

else {printf("参数错误\n");}

break;

}

case 2:

{

if(SubSMatrix_OL(&M, &N)){

printf("结果:\n");

PrintSMatrix_OL(M);

}

else {printf("参数错误\n");}

break;

}

case 3:

{

if(MultSMatrix_OL(M,N,&Q)){

printf("结果:\n");

PrintSMatrix_OL(Q);

}

else {printf("参数错误\n");}

break;

}

default: break;

}

}

}while(num == 1 || num == 2 || num == 3);

return 1;

}

5.程序的层次结构

层次结构

四、用户手册

本程序的运行环境为DOS操作系统,执行文件为:sparsematrix.exe和crossmatrix.exe 分别对应行逻辑链接顺序表和十字链表实现的稀疏矩阵计算器

进入程序按提示操作,输入要进行操作对应的序号

根据操作提示输入两矩阵的行数、列数和非零元个数,并输入非零元的行号,列号以及值

结果打印

根据操作提示退出程序

五、测试结果

\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

测试结果2

测试结果3

六、源代码

sparsematrix.c

#include

#include

#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;

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;

}

int PrintSMatrix(RLSMatrix M){

int row,col,t = 1;

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

for(col = 1; col <= M.nu; col++){

if(M.data[t].i == row && M.data[t].j == col){

printf("%d\t",M.data[t].e);

t++;

}else{

printf("0\t");

}

}

printf("\n");

}

return 1;

}

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;

}

int SubSMatrix(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;

}

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

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

int arow,brow;

int p,q,t,tp;

int ccol;

int ctemp[MAXRC + 1];

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

Q->mu = M.mu; Q->nu = N.nu; Q->tu = 0; // Q初始化

if(M.tu * N.tu != 0){ // Q是非零矩阵

for(arow = 1; arow <= M.mu; ++arow){ // 处理M的每一行

for(int i = 1; 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

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

ccol = N.data[q].j; // 乘积元素在Q中的列号

ctemp[ccol] += M.data[p].e * N.data[q].e;

}// for q

}// 求得Q中第crow(=arow)行的非零元

for(ccol = 1; ccol <= Q->nu; ++ccol){ //压缩储存改行非零元

if(ctemp[ccol]){

if(++Q->tu > MAXSIZE) return 0;

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

Q->data[Q->tu].j = ccol;

Q->data[Q->tu].e = ctemp[ccol];

}// if

} // for ccol

}// for arow

}// if

return 1;

}// MultSMatrix

int main(){

int num;

RLSMatrix M, N, Q;

do{

printf("操作:1.矩阵相加 2.矩阵相减 3.矩阵相乘 4.退出\n");

scanf("%d",&num);

if(num == 1 || num == 2 || num == 3){

printf("请输入矩阵1\n");

CreateSMatrix(&M);

printf("请输入矩阵2\n");

CreateSMatrix(&N);

printf("两矩阵为:\n");

PrintSMatrix(M);

printf("\n");

PrintSMatrix(N);

switch(num){

case 1:

{

if(AddSMatrix(M,N,&Q)){

printf("结果:\n");

PrintSMatrix(Q);

}

else {printf("参数错误\n");}

break;

}

case 2:

{

if(SubSMatrix(M,N,&Q)){

printf("结果:\n");

PrintSMatrix(Q);

}

else {printf("参数错误\n");}

break;

}

case 3:

{

if(MultSMatrix(M,N,&Q)){

printf("结果:\n");

PrintSMatrix(Q);

}

else {printf("参数错误\n");}

break;

}

default: break;

}

}

}while(num == 1 || num == 2 || num == 3);

return 1;

}

crosmatrix.c

#include

#include

#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;

int mu, nu, tu;

}CrossList;

int CreateSMatrix_OL(CrossList *M){

if(M) free(M);

int c;

int m,n,t;

int i,j,k,e;

OLink p,q;

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;

if(!(M->rhead = (OLink*)malloc((m+1)*sizeof(OLink)))) exit(-2);

if(!(M->chead = (OLink*)malloc((n+1)*sizeof(OLink)))) exit(-2);

for(c = 1; c <= M->mu; c++) M->rhead[c]=NULL;

for(c = 1; c <= M->nu; c++) M->chead[c]=NULL;

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);

if(!(p = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p->i = i; p->j = j; p ->e = e;

if(M->rhead[i] == NULL || M->rhead[i]->j > j){

p->right = M->rhead[i];

M->rhead[i] = p;

}else{

for(q = M->rhead[i]; (q->right) && (q->right->j < j); q = q->right);

p->right = q->right;

q->right = p;

}

if(M->chead[j] == NULL || M->chead[j]->i > i){

p->down = M->chead[j];

M->chead[j] = p;

}else{

for(q = M->chead[j]; (q->down) && (q->down->i < i); q = q->down);

p->down = q->down;

q->down = p;

}

}

return 1;

}

int PrintSMatrix_OL(CrossList M){

OLink p;

int row,col;

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

if(M.rhead[row]){

p = M.rhead[row];

for(col = 1; col <= M.nu; col++){

if(p->i == row && p->j == col && p != NULL){

printf("%d\t",p->e);

if(p->right) p = p->right;

}else{printf("0\t");}

}

}else{for(col = 1; col <= M.nu; col++) printf("0\t");}

printf("\n");

}

return 1;

}

int AddSMatrix_OL(CrossList *A, CrossList *B){

OLink pa, pb, pre, p, hl[MAXRC + 1];

int i, j;

if(A->mu != B->mu || A->nu != B->nu) return 0;

for(j = 1; j <= A->nu; j++) hl[j] = A->chead[j];

for(i = 1; i <= A->mu; i++){

pa = A->rhead[i]; pb = B->rhead[i]; pre = NULL;

while(pb){

if(!(p = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p->i = pb->i; p->j = pb->j; p->e = pb->e;

if(pa == NULL || pa->j > pb->j){

if(pre == NULL) A->rhead[p->i] = p;

else{pre->right = p; }

p->right = pa;

pre = p;

if(A->chead[p->j] == NULL || A->chead[p->j]->i > p->i){

p->down = A->chead[p->j];

A->chead[p->j] = p;

}else{

p->down = hl[p->j]->down;

hl[p->j]->down = p;

}

hl[p->j] = p;

pb = pb->right;

A->tu++;

}else if(pa && pa->j < pb->j){

pre = pa;

pa = pa->right;

}else if(pa->j == pb->j){

pa->e += pb->e;

if(pa->e == 0){

if(pre == NULL) A->rhead[pa->i] = pa->right;

else{pre->right = pa->right; }

p = pa; pa = pa->right;

if(A->chead[p->j] == p) A->chead[p->j] = hl[p->j] = p->down;

else{hl[p->j]->down = p->down; }

free(p);

pb = pb->right;

A->tu--;

}else{pre = pa; pa = pa->right; pb = pb->right; }

}

}

}

return 1;

}

int SubSMatrix_OL(CrossList *A, CrossList *B){

OLink pa, pb, pre, p, hl[MAXRC + 1];

int i, j;

if(A->mu != B->mu || A->nu != B->nu) return 0;

for(j = 1; j <= A->nu; j++) hl[j] = A->chead[j];

for(i = 1; i <= A->mu; i++){

pa = A->rhead[i]; pb = B->rhead[i]; pre = NULL;

while(pb){

if(!(p = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p->i = pb->i; p->j = pb->j; p->e = - pb->e;

if(pa == NULL || pa->j > pb->j){

if(pre == NULL) A->rhead[p->i] = p;

else{pre->right = p; }

p->right = pa;

pre = p;

if(A->chead[p->j] == NULL || A->chead[p->j]->i > p->i){

p->down = A->chead[p->j];

A->chead[p->j] = p;

}else{

p->down = hl[p->j]->down;

hl[p->j]->down = p;

}

hl[p->j] = p;

pb = pb->right;

A->tu++;

}else if(pa && pa->j < pb->j){

pre = pa;

pa = pa->right;

}else if(pa->j == pb->j){

pa->e -= pb->e;

if(pa->e == 0){

if(pre == NULL) A->rhead[pa->i] = pa->right;

else{pre->right = pa->right; }

p = pa; pa = pa->right;

if(A->chead[p->j] == p) A->chead[p->j] = hl[p->j] = p->down;

else{hl[p->j]->down = p->down; }

free(p);

pb = pb->right;

A->tu--;

}else{pre = pa; pa = pa->right; pb = pb->right; }

}

}

}

return 1;

}

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

int i, j, e;

OLink p, q, p1, rpre, cpre;

if(A.nu != B.mu) return 0;

C->mu = A.mu; C->nu = B.nu; C->tu = 0;

if(!(C->rhead = (OLink*)malloc((C->mu+1)*sizeof(OLink)))) exit(-2);

if(!(C->chead = (OLink*)malloc((C->nu+1)*sizeof(OLink)))) exit(-2);

for(i = 1; i <= C->mu; i++) C->rhead[i] = NULL;

for(j = 1; j <= C->nu; j++) C->chead[j] = NULL;

for(i = 1; i <= C->mu; i++){

for(j = 1; j <= C->nu; j++){

p = A.rhead[i]; q = B.chead[j]; e = 0;

while(p && q){

if(p->j > q->i){

q = q->down;

}else if(p->j < q->i){

p = p->right;

}else{

e += p->e * q->e;

q = q->down;

p = p->right;

}

}

if(e){

C->tu++;

if(!(p1 = (OLNode*)malloc(sizeof(OLNode)))) exit(-2);

p1->i = i; p1->j = j; p1->e = e;

p1->right = NULL; p1->down = NULL;

// 行插入

if(C->rhead[i] == NULL) {C->rhead[i] = p1; rpre = p1;}

else{rpre->right = p1; rpre = p1; }

// 列插入

if(C->chead[j] == NULL) {C->chead[j] = p1; cpre = p1;}

else{cpre->down = p1; cpre = p1; }

}

}

}

return 1;

}

int main(){

int num;

CrossList M, N, Q;

do{

printf("操作:1.矩阵相加 2.矩阵相减 3.矩阵相乘 4.退出\n");

scanf("%d",&num);

if(num == 1 || num == 2 || num == 3){

printf("请输入矩阵1\n");

CreateSMatrix_OL(&M);

printf("请输入矩阵2\n");

CreateSMatrix_OL(&N);

printf("两矩阵为:\n");

PrintSMatrix_OL(M);

printf("\n");

PrintSMatrix_OL(N);

switch(num){

case 1:

{

if(AddSMatrix_OL(&M, &N)){

printf("结果:\n");

PrintSMatrix_OL(M);

}

else {printf("参数错误\n");}

break;

}

case 2:

{

if(SubSMatrix_OL(&M, &N)){

printf("结果:\n");

PrintSMatrix_OL(M);

}

else {printf("参数错误\n");}

break;

}

case 3:

{

if(MultSMatrix_OL(M,N,&Q)){

printf("结果:\n");

PrintSMatrix_OL(Q);

}

else {printf("参数错误\n");}

break;

}

default: break;

}

}

}while(num == 1 || num == 2 || num == 3);

return 1;

}

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

  1. 稀疏矩阵 c语言,C语言数据结构 稀疏矩阵

    <C语言数据结构 稀疏矩阵>由会员分享,可在线阅读,更多相关<C语言数据结构 稀疏矩阵(4页珍藏版)>请在人人文库网上搜索. 1.实验十 稀疏矩阵#include #defin ...

  2. 数据结构 稀疏矩阵的实现方法

    稀疏矩阵的实现 什么是稀疏矩阵,怎么定义才是稀疏矩阵?假设在m x n的矩阵中,有t个不为0的元素.令z=t/(m x n),若z<=0.05则称此矩阵为稀疏矩阵.由于稀疏矩阵的非0元素较少,所 ...

  3. 数据结构C语言版字符串,数据结构c语言版

    数据结构c语言版是一款非常使用的数据结构课程的编写和教材:它也可将软件作为学习数据结构.算法C程序设计的参数教材,只需要用户学习该软件之后,就算遇到在繁杂的代码也可以清晰的写出来,本书的钱半部分主要介 ...

  4. C语言链表的转置算法,c语言编程集 数据结构 顺序表 点链表 数制转换 矩阵转置.doc...

    c语言编程集 数据结构 顺序表 点链表 数制转换 矩阵转置 #include "stdio.h" #include "malloc.h" /*typedef s ...

  5. rsa算法c语言实现_数据结构与算法之线性表-顺序表实现(C语言版本)

    原文托管在Github: https://github.com/shellhub/blog/issues/52 数据结构与算法之线性表-顺序表实现(C语言版本) 前言 数据结构与算法是一个程序员必备的 ...

  6. c语言将一个已知头结点的单链表逆序_C语言实现常用数据结构:静态链表数组实现(第5篇)...

    「今天是学习C语言第 148 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」 # 静态链表 使用数组实现,利用数组下标代替指针,从而实现数据结点之间的先后关系.实现要点: 1.数组 ...

  7. 算法与数据结构c语言版PPT,C语言算法与数据结构.ppt

    C语言算法与数据结构.ppt 第十二章 算法与数据结构12.1 算法的基本概念,该节知识点所占试题比重为12,属于重点考查对象,基本上每次必考,主要考查算法的定义和对算法复杂度的理解.历次试题分值在0 ...

  8. c语言系统的通用数据结构,(转载)C语言实现通用数据结构的高效设计

    (转载)C语言实现通用数据结构的高效设计 [复制链接] 使用宏替代模板的方案 最近在阅读一个开源的C++代码,里面用到了大量的STL里面的东西.也许是自己一直用C而很少用C++来实现算法的原因,STL ...

  9. aes算法c语言实现_C语言实现常用数据结构:Dijkstra最短路径算法(第18篇)

    「今天是学习C语言第 161 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」#题外话算法学习重点是学习如何编程使用它. # Dijkstra算法 Dijkstra算法,中文译名迪杰 ...

  10. 《Java语言程序设计与数据结构》编程练习答案(第七章)(一)

    <Java语言程序设计与数据结构>编程练习答案(第七章)(一) 英文名:Introduction to Java Programming and Data Structures, Comp ...

最新文章

  1. qt qgis linux,QGIS初识-Qt编译环境配置
  2. 南邮java实验一报告_南邮JAVA程序设计实验1 综合图形界面程序设计
  3. Nginx + FastCgi + Spawn-fcgi + c 的架构
  4. 简单快速开发C\S架构程序用最简单的不分层最快的效率达到功能要求的例子程序FrmKnowledge日积月累功能的实现...
  5. 以色列对话国际农民丰收节贸易会-万祥军:谋定无中生有
  6. Java18-day09【字节缓冲流、字符流、编码表、字符串与字符流中的编码解码问题、字符流读写数据的方式、字符缓冲流、IO流小结】
  7. jquery mobile用代码弹出dialog
  8. 自定义Exception异常
  9. k3c最新官改非常稳定了_软件聚分享库APP最新版下载-软件聚分享库v1.0.0安卓版下载...
  10. 记一次去掉中间的某次merge代码
  11. 算法设计与分析期末复习题
  12. 计算机操作系统哪几部分组成,计算机操作系统的组成部分
  13. 自媒体怎么做?5个操作步骤,普通人也可以做
  14. 小呆聚合支付系统免签约即时到账多商户支付系统v6.5+监控软件+教程
  15. 关于VS2017配置OpenCV出现无法打开文件“opencv_ml249d.lib”的解决方案
  16. 为什么我们会有假期一结束,快乐就终止的感觉?
  17. (已解决)INSTALL_FAILED_CONFLICTING_PROVIDER虚拟机安装失败错误
  18. 读书笔记—情商:为什么情商比智商更重要
  19. 优化滚动的一个小技巧:scroll-snap-type
  20. 计算机丢失mfc140ud.dll,mfc140ud.dll

热门文章

  1. 精简centos7.7内核版本升级
  2. McgsPro 运行期限
  3. 走近IT审计员(zt)
  4. douphp mysql版本_【公众号+小程序】DouPHP模块化企业网站管理系统版本号v1.6 – 最新版本 无后门 亲测...
  5. WSDL UDDI
  6. [转载]Ghost用法介绍
  7. antd tree 动态添加_CAD的动态块有什么用?(内附教程)
  8. openwrt无wan6口,如何设置ipv6
  9. 解决TqdmKeyError: “Unknown argument(s): {‘colour‘: ‘blue‘}“
  10. root lg android tv,首款Android 7.0手机LG V20发布,KingRoot教你玩转新系统