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

经过一周的课设,课设终于接近尾声了,期间重写了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

 

你可能感兴趣的:(数据结构)