1 /******************************************************
2 * *
3 * 文件夹: ▲05 数组和广义表\03 RowLinkSparseMatrix *
4 * *
5 * 文件名: RowLinkSparseMatrix.h *
6 * *
7 * 内 容: 行逻辑链接的顺序表(稀疏矩阵)相关操作列表 *
8 * *
9 ******************************************************/
10
11 #ifndef ROWLINKSPARSEMATRIX_H
12 #define ROWLINKSPARSEMATRIX_H
13
14 #include <stdio.h>
15 #include <stdarg.h> //提供宏va_list、va_start、va_arg、va_end
16 #include "../../01 绪论/Status.h" //**▲01 绪论**//
17 #include "../../01 绪论/Scanf.c" //**▲01 绪论**//
18
19 /* 宏定义 */
20 #define MAXSIZE 400 //假设非零元个数的最大值为400
21 #define MAXRC 20 //各行元素个数的最大值
22
23 /* 行逻辑链接的稀疏矩阵类型定义 */
24 typedef int MElemType_RLSq;
25 typedef struct
26 {
27 int i, j; //该非零元的行下标和列下标
28 MElemType_RLSq e;
29 }Triple;
30 typedef struct
31 {
32 Triple data[MAXSIZE+1]; //非零元三元组表data[0]未用
33 int rpos[MAXRC+1]; //各行第一个非零元在三元组表中的位置表
34 int mu, nu, tu; //矩阵的行数、列数和非零元个数
35 }RLSMatrix;
36
37 /* 行逻辑链接的顺序表(稀疏矩阵)基础操作 */
38 Status CreateSMatrix_RL(FILE *fp, int n, ...);
39 /*━━━━━━━━┓
40 ┃(01)创建矩阵M。 ┃
41 ┗━━━━━━━━*/
42
43 void DestroySMatrix_RL(RLSMatrix *M);
44 /*━━━━━━━┓
45 ┃(02)销毁矩阵。┃
46 ┗━━━━━━━*/
47
48 void PrintSMatrix_RL(RLSMatrix M);
49 /*━━━━━━━┓
50 ┃(03)输出矩阵。┃
51 ┗━━━━━━━*/
52
53 void CopySMatrix_RL(RLSMatrix M, RLSMatrix *T);
54 /*━━━━━━━━┓
55 ┃(04)矩阵的复制。┃
56 ┗━━━━━━━━*/
57
58 Status AddSMatri_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q);
59 /*━━━━━━━━┓
60 ┃(05)Q = M + N。 ┃
61 ┗━━━━━━━━*/
62
63 Status SubSMatrix_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q);
64 /*━━━━━━━━┓
65 ┃(06)Q = M - N。 ┃
66 ┗━━━━━━━━*/
67
68 Status MultSMatrix_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q);
69 /*━━━━━━━━━━━━┓
70 ┃(07)算法5.3:Q = M * N。┃
71 ┗━━━━━━━━━━━━*/
72
73 void TransposeSMatrix_RL(RLSMatrix M, RLSMatrix *T);
74 /*━━━━━━━┓
75 ┃(08)矩阵转置。┃
76 ┗━━━━━━━*/
77
78 void FastTransposeSMatrix_RL(RLSMatrix M, RLSMatrix *T);
79 /*━━━━━━━━━┓
80 ┃(09)矩阵快速转置。┃
81 ┗━━━━━━━━━*/
82
83 #endif
1 /****************************************************
2 * *
3 * 文件夹: ▲05 数组和广义表\03 RowLinkSparseMatrix *
4 * *
5 * 文件名: RowLinkSparseMatrix.c *
6 * *
7 * 算 法: 5.3 *
8 * *
9 ***************************************************/
10
11 #ifndef ROWLINKSPARSEMATRIX_C
12 #define ROWLINKSPARSEMATRIX_C
13
14 #include "RowLinkSparseMatrix.h" //**▲05 数组和广义表**//
15
16 Status CreateSMatrix_RL(FILE *fp, int n, ...)
17 {
18 int count, k;
19 RLSMatrix *M;
20
21 if(n<1)
22 return ERROR;
23
24 va_list ap;
25 va_start(ap, n);
26
27 for(count=1; count<=n; count++)
28 {
29 M = va_arg(ap, RLSMatrix *);
30
31 for(k=0; k<=MAXRC; ++k) //初始化数组rpos
32 (*M).rpos[k] = 0;
33
34 Scanf(fp, "%d%d%d", &((*M).mu), &((*M).nu), &((*M).tu));
35
36 for(k=1; k<=(*M).tu; k++)
37 {
38 Scanf(fp, "%d%d%d", &((*M).data[k].i), &((*M).data[k].j), &((*M).data[k].e));
39
40 if((*M).rpos[(*M).data[k].i]==0) //记录每行第一个非零元的位置
41 (*M).rpos[(*M).data[k].i] = k; //(只会在当前行有非零元的情况下记录)
42 }
43
44 for(k=(*M).mu; k>=1; --k) //处理那些没有非零元的行
45 {
46 if((*M).rpos[k]==0)
47 {
48 if(k==(*M).mu) //若最后一行无非零元,需特殊处理
49 (*M).rpos[k] = (*M).tu + 1;
50 else
51 (*M).rpos[k] = (*M).rpos[k+1];
52 }
53 }
54 }
55
56 va_end(ap);
57
58 return OK;
59 }
60
61 void DestroySMatrix_RL(RLSMatrix *M)
62 {
63 int i;
64
65 M->mu = 0;
66 M->nu = 0;
67 M->tu = 0;
68
69 for(i=0; i<=MAXRC; ++i)
70 M->rpos[i] = 0;
71 }
72
73 void PrintSMatrix_RL(RLSMatrix M)
74 {
75 int r, c;
76 int k = 1;
77
78 for(r=1; r<=M.mu; ++r)
79 {
80 for(c=1; c<=M.nu; ++c)
81 {
82 if(r==M.data[k].i && c==M.data[k].j)
83 {
84 printf("%3d ", M.data[k].e);
85 k++;
86 }
87 else
88 printf(" 0 ");
89 }
90 printf("\n");
91 }
92
93 printf("rpos = ");
94 for(k=1; k<=M.mu; ++k)
95 printf("%d ", M.rpos[k]);
96 printf("\n");
97 }
98
99 void CopySMatrix_RL(RLSMatrix M, RLSMatrix *T)
100 {
101 (*T) = M; //结构可以直接复制
102 }
103
104 Status AddSMatri_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
105 {
106 int m, n, k;
107 int i;
108
109 if(M.mu!=N.mu || M.nu!=N.nu)
110 {
111 printf("两矩阵不能相加!!\n");
112 return ERROR;
113 }
114
115 Q->mu = M.mu;
116 Q->nu = M.nu;
117 Q->tu = 0;
118 m = n = k = 1;
119
120 while(m<=M.tu && n<=N.tu) //依次遍历M与N的三元组
121 {
122 if(M.data[m].i<N.data[n].i)
123 {
124 Q->data[k] = M.data[m];
125 m++;
126 }
127 else if(M.data[m].i>N.data[n].i)
128 {
129 Q->data[k] = N.data[n];
130 n++;
131 }
132 else //M.data[m].i==N.data[n].i
133 {
134 if(M.data[m].j<N.data[n].j)
135 {
136 Q->data[k] = M.data[m];
137 m++;
138 }
139 else if(M.data[m].j>N.data[n].j)
140 {
141 Q->data[k] = N.data[n];
142 n++;
143 }
144 else //M.data[m].j==N.data[n].j
145 {
146 if(M.data[m].e+N.data[n].e)
147 {
148 Q->data[k].i = M.data[m].i;
149 Q->data[k].j = M.data[m].j;
150 Q->data[k].e = M.data[m].e+N.data[n].e;
151 m++;
152 n++;
153 }
154 else
155 {
156 m++;
157 n++;
158 continue;
159 }
160 }
161 }
162
163 k++;
164 Q->tu++;
165 }
166
167 while(m<=M.tu)
168 {
169 Q->data[k] = M.data[m];
170 m++;
171 k++;
172 Q->tu++;
173 }
174
175 while(n<=N.tu)
176 {
177 Q->data[k] = N.data[n];
178 n++;
179 k++;
180 Q->tu++;
181 }
182
183 for(i=0; i<=MAXRC; ++i) //初始化数组rpos
184 Q->rpos[i] = 0;
185
186 for(i=1; i<=Q->tu; ++i)
187 {
188 m = Q->data[i].i; //当前三元组中元素所在的行
189 if(Q->rpos[m]==0) //记录每行第一个非零元的位置
190 Q->rpos[m] = i; //(只会在当前行有非零元的情况下记录)
191 }
192
193 for(i=Q->mu; i>=1; --i) //处理那些没有非零元的行
194 {
195 if(Q->rpos[i]==0)
196 {
197 if(i==Q->mu) //若最后一行无非零元,需特殊处理
198 Q->rpos[i] = Q->tu + 1;
199 else
200 Q->rpos[i] = Q->rpos[i+1];
201 }
202 }
203
204 return OK;
205 }
206
207 Status SubSMatrix_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
208 {
209 int m, n, k;
210 int i;
211
212 if(M.mu!=N.mu || M.nu!=N.nu)
213 {
214 printf("两矩阵不能相减!!\n");
215 return ERROR;
216 }
217
218 Q->mu = M.mu;
219 Q->nu = M.nu;
220 Q->tu = 0;
221 m = n = k = 1;
222
223 while(m<=M.tu && n<=N.tu)
224 {
225 if(M.data[m].i<N.data[n].i)
226 {
227 Q->data[k] = M.data[m];
228 m++;
229 }
230 else if(M.data[m].i>N.data[n].i)
231 {
232 Q->data[k].i = N.data[n].i;
233 Q->data[k].j = N.data[n].j;
234 Q->data[k].e = -N.data[n].e;
235 n++;
236 }
237 else //M.data[m].i==N.data[n].i
238 {
239 if(M.data[m].j<N.data[n].j)
240 {
241 Q->data[k] = M.data[m];
242 m++;
243 }
244 else if(M.data[m].j>N.data[n].j)
245 {
246 Q->data[k].i = N.data[n].i;
247 Q->data[k].j = N.data[n].j;
248 Q->data[k].e = -N.data[n].e;
249 n++;
250 }
251 else //M.data[m].j==N.data[n].j
252 {
253 if(M.data[m].e-N.data[n].e)
254 {
255 Q->data[k].i = M.data[m].i;
256 Q->data[k].j = M.data[m].j;
257 Q->data[k].e = M.data[m].e-N.data[n].e;
258 m++;
259 n++;
260 }
261 else
262 {
263 m++;
264 n++;
265 continue;
266 }
267 }
268 }
269
270 k++;
271 Q->tu++;
272 }
273
274 while(m<=M.tu)
275 {
276 Q->data[k] = M.data[m];
277 m++;
278 k++;
279 Q->tu++;
280 }
281
282 while(n<=N.tu)
283 {
284 Q->data[k].i = N.data[n].i;
285 Q->data[k].j = N.data[n].j;
286 Q->data[k].e = -N.data[n].e;;
287 n++;
288 k++;
289 Q->tu++;
290 }
291
292 for(i=0; i<=MAXRC; ++i) //初始化数组rpos
293 Q->rpos[i] = 0;
294
295 for(i=1; i<=Q->tu; ++i)
296 {
297 m = Q->data[i].i; //当前三元组中元素所在的行
298 if(Q->rpos[m]==0) //记录每行第一个非零元的位置
299 Q->rpos[m] = i; //(只会在当前行有非零元的情况下记录)
300 }
301
302 for(i=Q->mu; i>=1; --i) //处理那些没有非零元的行
303 {
304 if(Q->rpos[i]==0)
305 {
306 if(i==Q->mu) //若最后一行无非零元,需特殊处理
307 Q->rpos[i] = Q->tu + 1;
308 else
309 Q->rpos[i] = Q->rpos[i+1];
310 }
311 }
312
313 return OK;
314 }
315
316 /*════╗
317 ║ 算法5.3║
318 ╚════*/
319 Status MultSMatrix_RL(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
320 {
321 int arow, brow, p, q, tp, tq, ccol;
322 int ctemp[N.nu+1]; //Q中各行元素值累加器,ctemp[0]不用
323 int i, m;
324
325 if(M.nu!=N.mu) //M列数等于N行数
326 {
327 printf("两矩阵不能相乘!!\n");
328 return ERROR;
329 }
330
331 Q->mu = M.mu; //Q初始化
332 Q->nu = N.nu;
333 Q->tu = 0;
334
335 if(M.tu*N.tu) //Q是非零矩阵
336 {
337 for(arow=1; arow<=M.mu; ++arow) //处理M的每一行
338 { //arow为乘积元素在Q中的行号
339 for(i=0; i<=N.nu; ++i) //初始化Q中行元素值计数器
340 ctemp[i] = 0;
341
342 if(arow<M.mu)
343 tp = M.rpos[arow+1]; //tp指向M当前行的下一行第一个非零元位置
344 else
345 tp = M.tu + 1;
346
347 for(p=M.rpos[arow]; p<tp; ++p) //p从M当前行第一个非零元位置开始累加
348 {
349 brow = M.data[p].j; //对M当前行中每一个非零元,找到对应元在N中的行号
350
351 if(brow<N.mu)
352 tq = N.rpos[brow+1]; //tq指向N当前行的下一行第一个非零元位置
353 else
354 tq = N.tu + 1;
355
356 for(q=N.rpos[brow]; q<tq; ++q) //q从N当前行第一个非零元位置开始累加
357 {
358 ccol = N.data[q].j; //乘积元素在Q中的列号
359 ctemp[ccol] += M.data[p].e * N.data[q].e;
360 }
361 }//Q中第arow行元素已求出
362
363 for(ccol=1; ccol<=Q->nu; ++ccol)
364 {
365 if(ctemp[ccol]) //若Q中第arow行ccol列元素不为0
366 {
367 ++Q->tu;
368 if(Q->tu>MAXSIZE) //非零元个数超出限制
369 return ERROR;
370 Q->data[Q->tu].i = arow;
371 Q->data[Q->tu].j = ccol;
372 Q->data[Q->tu].e = ctemp[ccol];
373 }
374 }//for(ccol)
375 }//for(arow)
376 }//if
377
378 for(i=0; i<=MAXRC; ++i) //初始化数组rpos
379 Q->rpos[i] = 0;
380
381 for(i=1; i<=Q->tu; ++i)
382 {
383 m = Q->data[i].i; //当前三元组中元素所在的行
384 if(Q->rpos[m]==0) //记录每行第一个非零元的位置
385 Q->rpos[m] = i; //(只会在当前行有非零元的情况下记录)
386 }
387
388 for(i=Q->mu; i>=1; --i) //处理那些没有非零元的行
389 {
390 if(Q->rpos[i]==0)
391 {
392 if(i==Q->mu) //若最后一行无非零元,需特殊处理
393 Q->rpos[i] = Q->tu + 1;
394 else
395 Q->rpos[i] = Q->rpos[i+1];
396 }
397 }
398
399 return OK;
400 }
401
402 void TransposeSMatrix_RL(RLSMatrix M, RLSMatrix *T)
403 {
404 int p, q, col;
405 int i, m;
406
407 T->mu = M.nu;
408 T->nu = M.mu;
409 T->tu = M.tu;
410
411 for(i=0; i<=MAXRC; ++i) //初始化数组rpos
412 T->rpos[i] = 0;
413
414 if(T->tu)
415 {
416 q = 1; //q用于T中非零元计数
417 for(col=1; col<=M.nu; ++col) //col代表M的列,T的行
418 {
419 for(p=1; p<=M.tu; ++p) //p用于M中非零元计数
420 {
421 if(M.data[p].j==col)
422 {
423 T->data[q].i = M.data[p].j; //M的列变为T的行
424 T->data[q].j = M.data[p].i; //M的行变为T的列
425 T->data[q].e = M.data[p].e; //每个三元组值不变
426
427 if(T->rpos[col]==0) //记录每行第一个非零元的位置
428 T->rpos[col] = q; //(只会在当前行有非零元的情况下记录)
429
430 ++q;
431 }
432 }
433 }
434 }
435
436 for(i=T->mu; i>=1; --i) //处理那些没有非零元的行
437 {
438 if(T->rpos[i]==0)
439 {
440 if(i==T->mu) //若最后一行无非零元,需特殊处理
441 T->rpos[i] = T->tu + 1;
442 else
443 T->rpos[i] = T->rpos[i+1];
444 }
445 }
446 }
447
448 void FastTransposeSMatrix_RL(RLSMatrix M, RLSMatrix *T)
449 {
450 int col, t, p, q;
451 int num[M.nu]; //num[col]表示M第col列中非零元的个数
452 int copt[M.nu]; //copt[col]表示M第col列第一个非零元在T->data中恰当的位置
453 int i, m;
454
455 T->mu = M.nu;
456 T->nu = M.mu;
457 T->tu = M.tu;
458
459 if(T->tu)
460 {
461 for(col=1; col<=M.nu; ++col)
462 num[col] = 0; //初始化数组num
463
464 for(t=1; t<=M.tu; ++t) //t遍历M中三元组
465 ++num[M.data[t].j]; //统计M中每列非零元个数
466
467 copt[1] = 1;
468 for(col=2; col<=M.nu; ++col)
469 copt[col] = copt[col-1] + num[col-1];
470
471 for(p=1; p<=M.tu; ++p) //依次扫描M中的三元组
472 {
473 col = M.data[p].j; //col为M中第p个三元组中元素的列
474 q = copt[col]; //q为当前三元组元素在T中应放置的位置
475 T->data[q].i = M.data[p].j;
476 T->data[q].j = M.data[p].i;
477 T->data[q].e = M.data[p].e;
478 ++copt[col]; //再遇到此列元素时位置增一
479 }
480 }
481
482 for(i=0; i<=MAXRC; ++i) //初始化数组rpos
483 T->rpos[i] = 0;
484
485 for(i=1; i<=T->tu; ++i)
486 {
487 m = T->data[i].i; //当前三元组中元素所在的行
488 if(T->rpos[m]==0) //记录每行第一个非零元的位置
489 T->rpos[m] = i; //(只会在当前行有非零元的情况下记录)
490 }
491
492 for(i=T->mu; i>=1; --i) //处理那些没有非零元的行
493 {
494 if(T->rpos[i]==0)
495 {
496 if(i==T->mu) //若最后一行无非零元,需特殊处理
497 T->rpos[i] = T->tu + 1;
498 else
499 T->rpos[i] = T->rpos[i+1];
500 }
501 }
502 }
503
504 #endif