数据结构课程设计:稀疏矩阵(加、减、乘、求逆矩阵)
经过一周的课设,课设终于接近尾声了,期间重写了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 }