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


    经过一周的课设,课设终于接近尾声了,期间重写了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个元素的行 列 及其值 
    ", 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("打开文件出错,看文件名是否输入正确,或者文件是否存在?
    ");
     99             printf("刚才输入的文件名为:%s
    ", 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 == '
    ')
    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 == '
    ')
    119                 break;
    120         }
    121         //在文件读取完成后,while都不执行,所以都要加1
    122 
    123         row++;
    124         col++;
    125         printf("矩阵信息读入成功,行数为: %d,列数为: %d 
    具体信息为 :", 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
    ", 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
    ", 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
     ", sum);
    399                 if(sum != 0)
    400                 {
    401                     /*printf("%lf
    ", 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
  • 相关阅读:
    linux实践之ELF文件分析
    《linux内核设计与实现》实践之模块及深入
    《linux内核设计与实现》读书笔记第十七章
    读书笔记——《沉思录》(4/4)
    读书笔记——《沉思录》(3/4)
    《Linux内核分析》期末总结
    20135337——linux第四次实践:字符集总结与分析
    20135337——Linux实践三:程序破解
    20135337——Linux实践三:ELF文件格式(64位系统,简单分析)
    20135337——linux实践三:ELF文件格式分析(32位系统)
  • 原文地址:https://www.cnblogs.com/ya-cpp/p/4210224.html
Copyright © 2020-2023  润新知