数据结构课程设计:稀疏矩阵(加、减、乘、求逆矩阵)

经过一周的课设,课设终于接近尾声了,期间重写了3边,第一次是变量名太混乱,各种瞎胡搞,“ii kk”这些奇葩变量都用上了,这次是一个警钟吧,要记住。第二次重写是因为,参照学长博客,但用到了指针的东西,自己指针学的渣,怕给组员讲不懂尴尬,所以,有了这最后一个版本。自我感觉,最后一个版本写的还可以,不过还是有一个小小的bug,今天中午写说明书的时候发现的,加法(减法用加法实现,当然也有),在计算时,最后一行就没进行运算。不会改了,就这样吧。最后附上PG的BLOG,看不懂我的,可以看他的。求逆矩阵,模拟是PG写的,我学他的。然后就是期末复习了,加油~~~

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 #define MAX_SIZE 1000
  6 int system(const char *string);// 调用系统命令
  7 
  8 typedef struct {
  9     int row, col;    //三元组表存储矩阵的行列,及其具体的值
 10     double val;
 11 }elem;
 12 
 13 typedef struct {
 14     elem data[MAX_SIZE];//三元组表数组
 15     int r, c, cnt;//三元组表存储实际矩阵的行列,及其非零元素的个数
 16     int r_cnt, c_cnt;//非零元的行数、列数
 17 }Matrix;
 18 
 19 Matrix a, b, c;//全局变量 三个用于运算的三元组表记录的矩阵
 20 
 21 void print_equal()
 22 {
 23     printf("================================================================================");
 24 }
 25 
 26 void print_menu()//打印菜单的函数
 27 {
 28     print_equal();
 29     printf("=                            1.矩阵A + 矩阵B                                   =");
 30     printf("=                            2.矩阵A - 矩阵B                                   =");
 31     printf("=                            3.矩阵A * 矩阵B                                   =");
 32     printf("=                            4.求矩阵A的逆矩阵                                 =");
 33     printf("=                            5.退出                                            =");
 34     print_equal();
 35 }
 36 
 37 void init(Matrix &m)//初始化三元组表里德元素
 38 {
 39     int i;
 40     m.r = m.c = m.cnt = 0; //使三元组表里的所有元素都为0
 41     m.r_cnt = m.c_cnt = 0;
 42 
 43     for(i = 0; i < MAX_SIZE; i++)
 44     {
 45         m.data[i].row = 0;
 46         m.data[i].col = 0;
 47         m.data[i].val = 0;
 48     }
 49 }
 50 
 51 void create_matrix(Matrix &m)///通过引用改变其值,very important!通过引用,可以不用创建新的形参,而直接在实参上边更改
 52 {
 53     int n1, n2, n3;
 54     FILE *in, *out;
 55     FILE *in1, *in2;
 56     char in_ch1, in_ch2;
 57     char filename[100];
 58     int cmd;
 59     int row, col;
 60     int r, c;
 61     double val;
 62     r = c = 0;
 63     row = col = 0;
 64     puts("==============================创建一个矩阵======================================");
 65     puts("                                1.手动以三元组表方式输入");
 66     puts("                                2.文件以矩阵的方式读入");
 67     print_equal();
 68     scanf("%d%*c", &cmd);
 69 
 70     if(cmd == 1)
 71     {
 72         puts("====================请输入矩阵的行数、列数、以及非零元的个数====================");
 73         scanf("%d %d %d", &n1, &n2, &n3);
 74         m.r = n1;            //下标都是从0开始的!!
 75         m.c = n2;
 76         m.cnt = n3;
 77         puts("                         请输入矩阵的非零行数、非零列数 ");
 78         scanf("%d %d", &n1, &n2);
 79         m.r_cnt = n1;
 80         m.c_cnt = n2;
 81         int i = 0;
 82         for(i = 0; i < m.cnt; i++)
 83         {
 84             printf("                   请输入第%d个元素的行 列 及其值 \n", i+1);
 85             scanf("%d %d %d", &n1, &n2, &n3);
 86             m.data[i].row = n1-1;
 87             m.data[i].col = n2-1;
 88             m.data[i].val = n3;
 89         }
 90     }
 91     else if(cmd == 2)
 92     {
 93         system("cls");
 94         puts("==============================输入要读入文件的文件名====================================");
 95         gets(filename);//read file's name
 96         if((in = fopen(filename, "r")) == NULL)
 97         {
 98             printf("打开文件出错,看文件名是否输入正确,或者文件是否存在?\n");
 99             printf("刚才输入的文件名为:%s\n", filename);
100             system("pause");
101             exit(0);
102         }
103         else 
104             printf("文件读取正常。。。");
105         in1 = fopen(filename, "r");
106         while(!feof(in1))
107         {
108             in_ch1 = fgetc(in1);
109             if(in_ch1 == '\n')
110                 row++;
111         }
112         in2 = fopen(filename, "r");
113         while(!feof(in2))
114         {
115             in_ch2 = fgetc(in2);
116             if(in_ch2 == ' ')
117                 col ++;
118             else if(in_ch2 == '\n')
119                 break;
120         }
121         //在文件读取完成后,while都不执行,所以都要加1
122 
123         row++;
124         col++;
125         printf("矩阵信息读入成功,行数为: %d,列数为: %d \n具体信息为 :", row, col);
126 
127         int i = 0;
128         while(!feof(in))
129         {
130             fscanf(in, "%lf", &val);
131             if(val != 0)
132             {
133                 m.data[i].val = val;
134                 m.data[i].row = r;
135                 m.data[i].col = c;
136                 printf("行值:%d, 列值 : %d, 数值:%0.2lf\n", r+1, c+1, val);
137                 i++;
138                 c++;
139                 m.cnt++;
140                 if(c == col)
141                 {
142                     c = 0;
143                     r ++;
144                 }
145             }
146             else if(val == 0)
147             {
148                 c ++;
149                 if(c == col)
150                 {
151                     c = 0;
152                     r++;
153                 }
154             }
155         }
156 
157         m.r = row;
158         m.c = col;
159     }
160 }
161 
162 void print_matrix(Matrix m)//打印矩阵的函数
163 {
164     /*printf("%d %d %d\n", m.r, m.c, m.cnt);*/
165     FILE *out;
166     char filename[100];
167     int row, col;
168     int i = 0;
169     int cmd;
170     puts("是否将结果打印在屏幕上?1.直接打印,2.写入到文件里。");
171     scanf("%d%*c", &cmd);
172 
173     if(cmd == 1)
174     {
175         for(row = 0; row < m.r; row++)
176         {
177             for(col = 0; col < m.c; col++)
178             {
179                 if(m.data[i].row == row && m.data[i].col == col)//如果在三元组表里找到当前元素,就输出,找不到,就输出0
180                 {
181                     printf("%0.2lf ", m.data[i].val);//格式控制
182                     i++;
183                 }
184                 else
185                 {
186                     printf("0.00 ");
187                 }
188             }
189             puts("");//换行
190         }
191     }else if(cmd == 2)
192     {
193         system("cls");
194         printf("输入要保存的文件名:");
195         scanf("%s", filename);
196         if((out = fopen(filename, "w")) == NULL)
197         {
198             printf("写入文件失败!!");
199             exit(0);
200         }
201         else 
202             puts("写入文件正常。");
203 
204         for(row = 0; row < m.r; row++)
205         {
206             for(col = 0; col < m.c; col++)
207             {
208                 if(m.data[i].row == row && m.data[i].col == col)
209                 {
210                     fprintf(out,"%0.2lf", m.data[i].val);
211                     fputc(' ', out);
212                     i++;
213                 }
214                 else
215                 {
216                     fprintf(out, "0.00");
217                     fputc(' ', out);
218                 }
219             }
220             fputc(10, out);
221         }
222         fclose(out);
223         puts("已保存!");
224     }
225 }
226 
227 void init_cmd() //初始化需要两个三元组表的矩阵
228 {
229     init(a);
230     init(b);
231     init(c);
232     system("pause");
233     system("cls");
234     create_matrix(a);
235     puts("===========================输入的矩阵以行列打印为:=============================");
236     print_matrix(a);
237     system("pause");
238     system("cls");
239 
240 
241     create_matrix(b);
242     puts("===========================输入的矩阵以行列打印为:=============================");
243 
244     print_matrix(b);
245     system("pause");
246     system("cls");
247 }
248 
249 int check(int cmd, Matrix m1, Matrix m2)//对输入的矩阵进行检查,看是否能够进行计算
250 {
251     if(cmd == 1 || cmd == 2)
252     {
253         if(m1.r == m2.r && m1.c == m2.c)
254             return 1;
255         return 0;
256     }
257     else if(cmd == 3)
258     {
259         if(m1.c == m2.r)
260             return 1;
261         return 0;
262     }
263 }
264 
265 void clear()//清屏,打印菜单
266 {
267     system("pause");
268     system("cls");
269     print_menu();
270 }
271 
272 //加法自己加注释
273 void add_matrix(Matrix m1, Matrix m2, Matrix &m3)
274 {
275     m3.r = m1.r;
276     m3.c = m2.c;
277     m3.cnt = 0;
278 
279     int i, j, k;
280     i = j = k = 0;
281     while((i < m1.cnt) && (j < m2.cnt))
282     {
283         if(m1.data[i].row == m2.data[j].row)
284         {
285             m3.data[k].row = m1.data[i].row;
286             if(m1.data[i].col < m2.data[j].col)
287             {
288                 m3.data[k].col = m1.data[i].col;
289                 m3.data[k].val = m1.data[i].val;
290                 k++; 
291                 i++;
292             }
293             else if(m1.data[i].col == m2.data[j].col)
294             {
295                 if(m1.data[i].val + m2.data[i].val != 0)
296                 {
297                     m3.data[k].col = m1.data[i].col;
298                     m3.data[k].val = m1.data[i].val + m2.data[i].val;
299                     k++; 
300                     i++; 
301                     j++;
302                 }
303                 else
304                 {
305                     i++;
306                     j++;
307                 }
308 
309             }
310             else if(m1.data[i].col > m2.data[j].col)
311             {
312                 m3.data[k].col = m2.data[j].col;
313                 m3.data[k].val = m2.data[j].val;
314                 k++;
315                 j++;
316             }
317         }
318         else if(m1.data[i].row < m2.data[j].row)
319         {
320             m3.data[k].row = m1.data[i].row;
321             m3.data[k].col = m1.data[i].col;
322             m3.data[k].val = m1.data[i].val;
323             k++;
324             i++;
325         }
326         else if(m1.data[i].row > m2.data[j].row)
327         {
328             m3.data[k].row = m2.data[j].row;
329             m3.data[k].col = m2.data[j].col;
330             m3.data[k].val = m2.data[j].val;
331             k++;
332             j++;
333         }
334     }
335 
336     while(i < m1.cnt)
337     {
338         m3.data[k].row = m1.data[i].row;
339         m3.data[k].col = m1.data[i].col;
340         m3.data[k].val = m1.data[i].val;
341         k++;
342         i++;
343     }
344     while(j < m2.cnt)
345     {
346         m3.data[k].row = m2.data[j].row;
347         m3.data[k].col = m2.data[j].col;
348         m3.data[k].val = m2.data[j].val;
349         k++;
350         j++;
351     }
352     
353     m3.cnt = k-1;
354     
355 }
356 
357 //乘法,自己加注释
358 void minus_matrix(Matrix m1, Matrix &m2, Matrix &m3)
359 {
360     int i = 0;
361     for(i = 0; i < m2.cnt; i++)
362         m2.data[i].val = -m2.data[i].val;
363     add_matrix(m1, m2, m3);
364 }
365 
366 double value(Matrix m, int row, int col)
367 {
368     int i = 0;
369     while(i < m.cnt && m.data[i].row <= row)
370     {
371         if(m.data[i].row == row && m.data[i].col == col)
372             return m.data[i].val;
373         i++;
374     }
375     return 0.0;
376 }
377 
378 void mul_matrix(Matrix m1, Matrix m2, Matrix &m3)
379 {
380     int i, j, k, tag;
381     double sum = 0;
382     m3.r = m1.r;
383     m3.c = m2.c;
384     m3.cnt = 0;
385 
386     if(m1.cnt * m2.cnt != 0)
387     {
388         tag = 0;
389         for(i = 0; i < m1.r; i++)
390         {
391             for(j = 0; j < m2.c; j++)
392             {
393                 sum = 0;
394                 for(k = 0; k < m1.c; k++)
395                 {
396                     sum += value(m1, i, k) * value(m2, k, j);
397                 }
398                 //printf("%lf\n ", sum);
399                 if(sum != 0)
400                 {
401                     /*printf("%lf\n", sum);*/
402                     m3.data[tag].row = i;
403                     m3.data[tag].col = j;
404                     m3.data[tag].val = sum;
405                     tag++;
406                 }
407             }
408         }
409         m3.cnt = tag;
410     }
411 }
412 
413 //思路就是通过初等变换求逆矩阵
414 int inversion(Matrix m1, Matrix m2, Matrix &m3)
415 {
416     int i, j, k;
417     /* 初始化构建的矩阵的三元组表*/
418     m2.r = m1.r;
419     m2.c = m1.c*2;
420     m2.cnt = m2.r * m2.c;
421 
422     int row, col;
423     row = col = 0;
424     //初始化三元组表里每个元素的行列值
425     for(i = 0; i < m2.cnt; i++)
426     {
427         m2.data[i].val = 0;
428         m2.data[i].row = row;
429         m2.data[i].col = col;
430 
431         col++;
432         if(col == m2.c)
433         {
434             col = 0;
435             row++;
436         }
437     }
438     //初始化非零元素的具体值
439     for(i = 0; i < m1.cnt; i++)
440     {
441         for(j = 0; j < m2.cnt; j++)
442         {
443             if(m2.data[j].row == m1.data[i].row && m2.data[j].col == m1.data[i].col)
444             {
445                 m2.data[j].val = m1.data[i].val;
446             }
447         }
448     }
449 
450     //运用公式,初始化单位矩阵
451     j = 0;
452     double n1, n2, n3, t, x ;
453     n1 = n2 = 1.0;
454     for(i = 0; i < m1.r; i++)
455     {
456         m2.data[j*m2.c+i+m2.r].val = 1;
457         j++;
458     }
459 
460     int row1;
461     //print_matrix(m2);
462     for(col = 0; col < m2.r; col++){
463         for(row = 0; row < m2.r; row++){
464             if(row != col){
465                 for(i = 0; i < m2.cnt; i++){
466                     if(m2.data[i].row == row && m2.data[i].col == col){
467                         n1 = m2.data[i].val;
468                         break;
469                     }
470                 }
471 
472                 //取对角线上的值
473                 for(i = 0; i < m2.cnt; i++){
474                     if(m2.data[i].row == col && m2.data[i].col == col){
475                         n2 = m2.data[i].val;
476                         break;
477                     }
478                 }
479 
480                 t = n1 / n2;
481                 //通过两重循环将每个值取出,然后乘以倍数,减去得到相应的值
482                 for(i = 0; i < 2*m2.r; i++)
483                 {
484                     for(j = 0; j < m2.cnt; j++){
485                         if(m2.data[j].row == col && m2.data[j].col == i){
486                             n3 = m2.data[j].val;
487                             break;
488                         }
489                     }
490 
491                     x = n3 * t;
492                     for(k = 0; k < m2.cnt; k++)
493                     {
494                         if(m2.data[k].row == row && m2.data[k].col == i){
495                             m2.data[k].val -= x;
496                             break;
497                         }
498                     }
499                 }
500 
501                 int tag = 0;
502                 //鉴别能否求逆
503                 for(row1 = 0; row1 < m2.r; row1++) {
504                     tag = 0;
505                     for(i = 0; i < m2.cnt; i++) {
506                         if(m2.data[i].row == row1 ) {
507                             if(m2.data[i].val == 0)
508                                 tag++;
509                             if(tag == m1.c)
510                             {
511                                 return 0 ;
512                             }
513                         }    
514                     }
515                 }
516             }
517         }
518     } 
519     row = col = 0;
520     i = j = k = 0;
521     n1 = n2 = n3 = 0;
522     //将主对角线上的元素单位话
523     for(row = 0; row < m2.r; row++){
524         for(i = 0; i < m2.cnt; i++){
525             if(m2.data[i].row == row && m2.data[i].col == row){
526                 n1 = m2.data[i].val;
527                 break;
528             }
529         }
530         //同除以一个数,使前一个矩阵变为单位矩阵
531         for(col = 0; col < m2.c; col++) {
532             for(i = 0; i < m2.cnt; i++) {
533                 if(m2.data[i].row == row && m2.data[i].col == col) {
534                     m2.data[i].val /= n1;
535                     break;
536                 }
537             }
538         }
539     }
540 
541     row = col;
542 
543     int r, c;
544     r = c = 0;
545 
546     m3.cnt = m2.cnt / 2;
547     m3.r = m2.r;
548     m3.c = m2.r;
549     for(i = 0; i < m3.cnt; i++){
550         m3.data[i].val = m2.data[i + (r+1)*m2.r].val;
551         m3.data[i].row = m2.data[i + (r+1)*m2.r].row;
552         m3.data[i].col = m2.data[i + (r+1)*m2.r].col - m2.r;
553         c++;
554         if(c == m3.r) {
555             c = 0;
556             r++;
557 
558         }
559     }
560     return 1;
561 }
562 
563 int main()
564 {
565     //freopen("in.txt", "r", stdin);
566     //freopen("out.txt", "w", stdout);
567     int cmd;
568     int tag = 0;
569     print_menu();
570     //switch case 语句
571     while(scanf("%d", &cmd) != EOF){
572         switch(cmd){
573         case 1:{
574             init_cmd();
575             if(check(cmd, a, b) == 1){
576                 //加法
577                 add_matrix(a, b, c);
578                 puts("=========================加法求得的矩阵以行列打印为:===========================");
579                 print_matrix(c);
580             }
581             else 
582                 puts("输入的两个矩阵不能进行加法计算!");
583             clear();
584             break;
585                }
586         case 2: {
587             init_cmd();
588             if(check(cmd, a, b) == 1){
589                 //减法
590                 minus_matrix(a, b, c);
591                 puts("=========================减法求得的矩阵以行列打印为:===========================");
592                 print_matrix(c);
593             }
594             else 
595                 puts("输入的两个矩阵不能进行减法计算!");
596             clear();
597             break;
598                 }
599 
600         case 3:{
601             init_cmd();
602             if(check(cmd, a, b) == 1){
603                 //乘法
604                 mul_matrix(a, b, c);
605                 puts("=========================乘法求得的矩阵以行列打印为:===========================");
606                 print_matrix(c);
607             }
608             else 
609                 puts("输入的两个矩阵不能进行乘法计算!");
610             clear();
611             break;
612                }
613         case 4:{
614             //求逆
615             system("pause");
616             system("cls");
617             init(a);
618             create_matrix(a);
619             init(b);
620             init(c);
621             if(a.r == a.c){
622                 tag = inversion(a, b, c);
623                 if(tag == 0)
624                     puts("===========================输入的矩阵无逆矩阵!==============================");
625                 else{
626                     puts("=========================原矩阵的逆矩阵以行列打印为:===========================");
627                     print_matrix(c);
628                 }
629             }
630             else
631                 puts("===========================输入的矩阵无逆矩阵!==============================");
632             clear();
633             break;
634                }
635         case 5:
636             return 0;
637             break;
638         }
639     }
640 
641     return 0;
642 }
View Code

 

posted @ 2015-01-08 10:33  unicoe  阅读(640)  评论(0编辑  收藏  举报