稀疏矩阵——行逻辑定义及相关操作列表

Posted hongdoudou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了稀疏矩阵——行逻辑定义及相关操作列表相关的知识,希望对你有一定的参考价值。

 1 /******************************************************
 2  *                                                      *
 3  * 文件夹: ▲05 数组和广义表3 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 数组和广义表3 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("
");
 91     }
 92     
 93     printf("rpos = ");
 94     for(k=1; k<=M.mu; ++k)
 95         printf("%d ", M.rpos[k]);
 96     printf("
");
 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("两矩阵不能相加!!
");
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("两矩阵不能相减!!
");
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("两矩阵不能相乘!!
");
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

 

以上是关于稀疏矩阵——行逻辑定义及相关操作列表的主要内容,如果未能解决你的问题,请参考以下文章

稀疏矩阵的存储和乘法操作

行逻辑链接的矩阵乘法

5-3-行逻辑链接的顺序表(稀疏矩阵)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版

python中scipy学习——随机稀疏矩阵及操作

Numba 中的稀疏矩阵

稀疏矩阵的运算