数据结构课程设计报告n维矩阵乘法


     数据结构 课程设计报告 设计题目: n维矩阵乘法:A B-1 专 业 计算机科学与技术 班 级 计本 学 生 学 号 指导教师 起止时间 2007.X.3-2007.X.11 学年第 I 学期 一、 具体任务 功能: 设计一个矩阵相乘的程序,首先从键盘输入两个矩阵a,b的内容,并输出两个矩阵,输出ab-1结果。 分步实施: 1.初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数; 2.完成最低要求:建立一个文件,可完成2维矩阵的情况; 3.进一步要求:通过键盘输入维数n。有兴趣的同学可以自己扩充系统功能。 要求: 1.界面友好,函数功能要划分好 2.总体设计应画一流程图 3.程序要加必要的注释 4.要提供程序测试方案 5.程序一定要经得起测试,宁可功能少一些,也要能运行起来,不能运行的程序是没有价值的。 二、 软件环境 Microsoft Visual C++ 6.0 三、 问题的需求分析 程序以二维数组作为矩阵的存储结构,通过键盘输入矩阵维数n,动态分配内存空间,创建n维矩阵。矩阵建立后再通过键盘输入矩阵的各个元素值;也可以通过文件读入矩阵的各项数据(维数及各元素值)。 当要对矩阵作进一步操作(A*B或A*B^(-1))时,先判断内存中是否已经有相关的数据存在,若还未有数据存在则提示用户先输入相关数据。 当要对矩阵进行求逆时,先利用矩阵可逆的充要条件:|A| != 0 判断矩阵是否可逆,若矩阵的行列式 |A| = = 0 则提示该矩阵为不可逆的;若 |A| !=0 则求其逆矩阵,并在终端显示其逆矩阵。 四、 算法设计思想及流程图 1.抽象数据类型 ADT MatrixMulti{ 数据对象:D = {a(I,j)|i = 1,2,3,…,n;j = 1,2,…,n;a(i,j)∈ElemSet,n为矩阵维数} 数据关系: R = {Row,Col} Row = {<a(i,j),a(i,j+1)>| 1 <= i <= n , 1 <= j <= n-1} Col = {<a(i,j),a(i+1,j)>| 1 <= i <= n-1 , 1 <= j <= n} 基本操作: Swap(&a,&b); 初始条件:记录a,b已存在。 操作结果:交换记录a,b的值。 CreateMatrix(n); 操作结果:创建n维矩阵,返回该矩阵。 Input(&M); 初始条件:矩阵M已存在。 操作结果:从终端读入矩阵M的各个元素值。 Print(&M) 初始条件:矩阵M已存在。 操作结果:在终端显示矩阵M的各个元素值。 ReadFromFile(); 操作结果:从文件读入矩阵的相关数据。 Menu_Select(); 操作结果:返回菜单选项。 MultMatrix(&M1,&M2,&R); 初始条件:矩阵M1,M2,R已存在。 操作结果:矩阵M1,M2作乘法运算,结果放在R中。 DinV(&M,&V); 初始条件:矩阵M,V已存在。 操作结果:求矩阵M的逆矩阵,结果放入矩阵V中。 MatrixDeterm(&M,n); 初始条件:矩阵M已存在。 操作结果:求矩阵M的行列式的值。 } ADT MatrixMulti 2.矩阵求逆算法设计思想 算法采用高斯-约旦法(全选主元)求逆,主要思想如下: 首先,对于k从0到n-1作如下几步: ① 从第k行、第k列开始的右下角子阵中选取绝对值最大的元素,并记住此元素所在的行号与列号,再通过行交换和列交换将它交换到主元素位置上。这一步称为全选主元。 ② 主元求倒:M(k,k) = 1 / M(k,k) ③ M(k,j) = M(k,j) * M(k,k);j = 0,1,…,n-1;j != k ④ M(i,j) = M(i,j) – M(i,k) * M(k,j);i,j = 0,1,…,n-1;i,j!=k ⑤ M(i,k) = - M(i,k) * M(k,k),i = 0,1…,n-1;i != k 最后,根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复原则如下: 在全选主元过程中,先交换的行(列)后进行恢复;原来的行(列)交换用列(行)交换来恢复。 3.矩阵行列式求值运算算法设计思想 利用行列式的性质:行列式等于它的任一行(列)各元素与其对应的代数余子式乘积,即 D = ∑a(i,k)*A(i,k) ; k = 1,2,…,n; D = ∑a(k,j)*A(k,j) ; k = 1,2,…,n; 再利用函数的递归调用法实现求其值。 4.各函数间的调用关系 Main() ReadFromFile() DinV() Swap () Print() Menu_Select() MatrixDeterm() CreateMatrix() MultMatrix() Input() 5.流程图 否 否 是 否 是 是 否 是 否 否 是 开始 switch(Menu_Select()) case 1: case 3: case 2: n > 0 ? 是 输入矩阵维数n 输入矩阵A,B 输出矩阵维数n system(“pause”); 通过键盘输入需对哪个矩阵求逆,求出相应该的逆阵,并显示求得的逆阵system(“pause”);若矩阵不可逆则返回主菜单 case 4: R=A*B并显示矩阵R system(“pause”); case 5: 是 否 是 R=A*B^(-1)显示矩阵R system(“pause”);若B不可逆,则返回主菜单 case 6: 从指定文件中读入矩阵数据 case 0: exit(0); 结果 否 五、 源代码 #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <malloc.h> #include <string.h> #define YES 1 #define NO 0 typedef float ElemType; ElemType **A; //矩阵A ElemType **B; //矩阵B ElemType **R; //矩阵R,用于存放运算结果 ElemType **V; //矩阵V,存放逆矩阵 int n=0; //矩阵维数 int flag=-1; //标记 void swap(ElemType *a,ElemType *b) //交换记录a,b的值 { ElemType c; c=*a; *a=*b; *b=c; } ElemType **CreateMatrix(int n) //创建n维矩阵,返回该矩阵 { int i,j; ElemType **M; M = (ElemType **)malloc(sizeof(ElemType *)*n); if(M == NULL) exit(1); for(i=0;i<n;i++) { *(M+i) = (ElemType *)malloc(sizeof(ElemType)*n); for(j=0;j<n;j++) *(*(M+i)+j) = 0; } return M; } ElemType MatrixDeterm(ElemType **M,int n) /*递归法求n维矩阵行列式的值,返回运算结果*/ { int i,j,k,l,s; ElemType **T1; ElemType **T2; T1=CreateMatrix(n); T2=CreateMatrix(n); ElemType u; ElemType value=0; //运算结果 for(i=0;i<n;i++) { for(j=0;j<n;j++) { T1[i][j]=M[i][j]; T2[i][j]=M[i][j]; } } if(n==2) //若为2维矩阵,则直接运算并返回运算结果 { value=T2[0][0]*T2[1][1]-T2[0][1]*T2[1][0]; return value; } else { for(j=0;j<n;j++) //将矩阵的行列式以第一行展开 { u=T1[0][j]; for(i=1,l=0;i<n;i++) //求矩阵行列式的余子式M(0,j) { for(k=0,s=0;k<n;k++) { if(k==j) continue; else { T2[l][s]=T1[i][k]; s++; } } l++; } value=value+u*((int)pow(-1,j))*MatrixDeterm(T2,n-1); /*行列式等于某一行的各个元素与其代数余子式的乘积之和*/ } return value; } } int DinV(ElemType **M,ElemType **V) /*全选主元法求矩阵M的逆矩阵,结果存入矩阵V中*/ { int i,j,k; ElemType d; ElemType u; int *JS,*IS; JS=(int *)malloc(sizeof(int)*n); IS=(int *)malloc(sizeof(int)*n); u=MatrixDeterm(M,n); //返回矩阵A的行列式值 if(u==0) return -1; for(i=0;i<n;i++) for(j=0;j<n;j++) V[i][j]=M[i][j]; for(k=0;k<n;k++) { d=0; for(i=k;i<n;i++) //找出矩阵M从M[k][k]开始绝对值最大的元素 { for(j=k;j<n;j++) { if(fabs(V[i][j])>d) { d=fabs(V[i][j]); //d记录绝对值最大的元素的值 /*把绝对值最大的元素在数组中的行、列坐标分别存入IS[K],JS[K]*/ IS[k]=i; JS[k]=j; } } } if(d+1.0 == 1.0) return 0; //所有元素都为0 if(IS[k] != k) /*若绝对值最大的元素不在第k行,则将矩阵IS[K]行的元素与k行的元素相交换*/ for(j=0;j<n;j++) swap(&V[k][j],&V[IS[k]][j]); if(JS[k]!=k) /*若绝对值最大的元素不在第k列,则将矩阵JS[K]列的元素与k列的元素相交换*/ for(i=0;i<n;i++) swap(&V[i][k],&V[i][JS[k]]); V[k][k]=1/V[k][k]; //绝对值最大的元素求倒 for(j=0;j<n;j++) /*矩阵M第k行除元素M[k][k]本身外都乘以M[k][k]*/ if(j!=k) V[k][j]=V[k][j]*V[k][k]; for(i=0;i<n;i++) /*矩阵除第k行的所有元素与第k列的所有元素外,都拿本身减去M[i][k]*M[k][j], 其中i,j为元素本身在矩阵的位置坐标*/ if(i!=k) for(j=0;j<n;j++) if(j!=k) V[i][j]=V[i][j]-V[i][k]*V[k][j]; for(i=0;i<n;i++) /*矩阵M第k列除元素M[k][k]本身外都乘以-M[k][k]*/ if(i!=k) V[i][k]=-V[i][k]*V[k][k]; } for(k=n-1;k>=0;k--) /*根据上面记录的行IS[k],列JS[k]信息恢复元素*/ { for(j=0;j<n;j++) if(JS[k]!=k) swap(&V[k][j],&V[JS[k]][j]); for(i=0;i<n;i++) if(IS[k]!=k) swap(&V[i][k],&V[i][IS[k]]); } free(IS); free(JS); return 0; } void MultMatrix(ElemType **M1,ElemType **M2,ElemType **R) /*矩阵M1乘M2 结果存入矩阵R*/ { int i,j,k; for(i=0;i<n;i++) { for(j=0;j<n;j++) { R[i][j]=0; } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { for(k=0;k<n;k++) { R[i][j]=R[i][j]+M1[i][k]*M2[k][j]; } } } } void Input(ElemType **M) //输入矩阵M的各个元素值 { int i,j; char str[10]; char c='A'; if(flag==1) c='B'; system(“cls“); printf(“\n\n输入矩阵%c(%d*%d)\n“,c,n,n); for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf(“%f“,*(M+i)+j); } } flag=1; gets(str); //吸收多余的字符 } void Print(ElemType **M) //显示矩阵M的各个元素值 { int i,j; printf(“\t“); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf(“ %.3f“,M[i][j]); } puts(““); printf(“\t\t“); } } int Menu_Select() { char c; do{ system(“cls“); puts(“\t\t*************n维矩阵乘法器*************“); puts(“\t\t| 1. 通过键盘输入各项数据 |“); puts(“\t\t| 2. 显示矩阵A,B |“); puts(“\t\t| 3. 矩阵求逆,并显示逆矩阵 |“); puts(“\t\t| 4. 求矩阵运算A*B,并显示运算结果 |“); puts(“\t\t| 5. 求矩阵运算A*B^(-1),并显示运算结果|“); puts(“\t\t| 6. 从文件读入矩阵A,B与维数n |“); puts(“\t\t| 0. 退出 |“); puts(“\t\t***************************************“); printf(“\t\t请选择(0-6):“); c=getchar(); }while(c<'0'||c>'6'); return (c-'0'); } void ReadFromFile() //从指定文件读入矩阵的维数及矩阵各元素的值 { int i,j; FILE *fp; if((fp=fopen(“tx.txt“,“r“))==NULL) { puts(“无法打开文件!!!“); system(“pause“); exit(0); } fscanf(fp,“%d“,&n); //读入矩阵维数 A=CreateMatrix(n); //创建矩阵A B V R B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); for(i=0;i<n;i++) //读入矩阵A { for(j=0;j<n;j++) { fscanf(fp,“%f“,&A[i][j]); } } for(i=0;i<n;i++) //读入矩阵A { for(j=0;j<n;j++) { fscanf(fp,“%f“,&B[i][j]); } } puts(“\n\n读文件成功“); fclose(fp); flag=1; } int main() { int i; char c,h; char str[10]; for(;;) { switch(Menu_Select()) { case 1: flag=-1; for(;;) { system(“cls“); printf(“\n\n\t矩阵维数n:“); scanf(“%d“,&n); gets(str); if(n>0) break; else { printf(“\n\t输入有误,请重新输入!\n“); puts(““); system(“pause“); } } A=CreateMatrix(n); B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); Input(A); Input(B); break; case 2: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } puts(“\n“); printf(“\tA = “); Print(A); puts(“\n“); printf(“\tB = “); Print(B); puts(““); system(“pause“); break; case 3: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } for(;;) { printf(“\n\n\t输入需要求逆的矩阵(A/B):“); h=getchar(); c=getchar(); //h=getchar(); if(c=='A'||c=='a') { i=DinV(A,V); if(i==-1) { puts(“\n\n\t矩阵A的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tA = “); Print(A); puts(“\n“); printf(“A^(-1) = “); Print(V); puts(““); system(“pause“); break; } else if(c=='B'||c=='b') { i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩阵B的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tB = “); Print(B); puts(“\n“); printf(“B^(-1) = “); Print(V); puts(““); system(“pause“); break; } else puts(“\n\n\t输入有误,请重新输入!\n“); } break; case 4: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } MultMatrix(A,B,R); printf(“\n\n\tA*B = “); Print(R); puts(““); system(“pause“); break; case 5: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩阵B的行列式等于0,不可逆!“); system(“pause“); break; } MultMatrix(A,V,R); printf(“\n\nA*B^(-1) = “); Print(R); puts(““); system(“pause“); break; case 6: system(“cls“); ReadFromFile(); puts(““); system(“pause“); break; case 0: puts(“\t\t正常退出“); exit(0); break; } } return 0; } 六、 运行结果 1.主界面: 2.输入6,回车,从文本文件tx.txt中读入矩阵数据: 3.回车,回到主菜单界面;输入2回车,显示从文件读入的矩阵数据: 4.回车,回到主菜单界面;输入3回车,对指定矩阵求逆:(由于这里矩阵A是不可逆的,因此仅以矩阵B为例) 5.回车,回到主菜单界面;输入4回车,求矩阵运算A*B: 6.回车回到主菜单界面,输入5回车,求A*B^(-1)的值: 7.回车回到主菜单界面,输入0回车,退出程序;如果需要自定矩阵维数及各元素值,请利用主菜单里的1号功能自行输入数据,再进行以上几种运算操作。 七、 收获及体会 通过这次课程设计,让我再次复习了线性代数里矩阵的相关知识,比如n维矩阵的求逆、矩阵可逆的充分必要条件(|A| != 0)、矩阵与矩阵的乘法运算、行列式求值方法等。同样的,还让我复习了大量C语言里有关数组的一些重要概念,比如多维数组的动态分配问题、数组与指针的关系等。 记得在这个学期新开设的单片机基础课上,吴涛老师曾多次强调,让我们一定要经常锻炼自己的编程能力,他常对我们说:“编程是思维的体操。”尽管我在这方面的能力 和实力非常得有限,也远远不及班上的其他同学,但我通过这次课程设计充分体会到了这句话的精华。 电脑程序作为人体大脑思维的延伸,程序的功能也会因为大脑思维的不断完善而变得更加强大,所以我决定今后要加强在这方面的锻炼和学习,以此来激励自己不断前进! 八、 参考文献 《数据结构(C语言版)》 严蔚敏,吴伟民 编著 清华大学出版社 《C语言程序设计》 洪维恩 编著 中国铁道出版社 《C语言程序设计教程》 谭浩强 张基温 唐永炎 编著 高等教育出版社 《工程数学——线性代数 第四版》 同济大学应用数学系 编 高等教育出版社 计本 2007-12 本文档由香当网(https://www.xiangdang.net)用户上传

    下载文档到电脑,查找使用更方便

    文档的实际排版效果,会与网站的显示效果略有不同!!

    需要 4 香币 [ 分享文档获得香币 ]

    下载文档

    相关文档

    数据结构课程设计报告n维矩阵乘法

    设计一个矩阵相乘的程序,首先从键盘输入两个矩阵a,b的内容,并输出两个矩阵,输出ab-1结果。

    2周前    121    0

    关于数据结构课程设计心得体会范文

    关于数据结构课程设计心得体会范文   关于数据结构课程设计心得体会(1)   这学期开始两周时间是我们自己选题上机的时间, 这学期开始两周时间是我们自己选题上机的时间,虽然 上机时间只...

    1年前    478    0

    环保“四维矩阵”监管模式

    创新工作机制促进投诉受理工作再上新台阶 环保“四维矩阵”监管模式  近年来,**区经济社会迎来了又一轮的飞速发展,人民群众对周边环境的关心也日益增强,随之而来暴露出的环保问题亦是越来越多,...

    8年前    10689    0

    第N份 项目进展报告

       第N份 项目进展报告 来自:http://www.chinaspis.com 作者:林锐 电子工业出版社出版发行   基本信息 项目名称   报告日期   项目...

    6年前    1811    0

    日期和时间课程设计报告

    日期和时间课程设计报告 1. 功能 1.1课程设计题目功能:定义了日期类、时间类和日期时间综合类,重载了+、-、++、--、=、>=、<=、==、!=等运算符,可以设置时间、日期,比较时间和日...

    1年前    505    0

    单片机课程设计报告

    1 方案设计与论证1.1 硬件总体设计设计并制作一个基于单片机的数字电压表的电路其结构框图如图 1-1 所示: 图1-1 硬件结构框图(1)单片机最小系统电路部分 (2)数码管显示部分(3) ...

    10个月前    567    0
    报告  

    任意两个高次多项式的加法和乘法运算课程设计

     课程设计报告 设计名称: 数据结构课程设计 设计题目: 任意两个高次多项式的加法和乘法运...

    1年前    288    0

    第N份 质量保证报告

       第N份 质量保证报告 来自:http://www.chinaspis.com 作者:林锐 电子工业出版社出版发行 基本信息 项目名称   报告日期   质量保...

    10年前    26279    0
    报告   工作   总结   信息   项目  

    Web系统开发课程设计报告

    录入学生基本信息的功能学生基本信息主要包括:学号、姓名、年龄、出生地、专业、班级总学分,在插入时,如果数据库已经存在该学号,则不能再插入该学号。1.2、修改学生基本信息的功能

    4周前    328    0

    物流系统课程设计报告书

     XX大学 物流系统课程设计报告书 学院名称 : 经济与学院 学生姓名 : 专业名称 : 物流管理 班级 : 物流班 时间 ...

    1年前    680    0

    多媒体课程设计小组小结报告

    计算机多媒体基础小结报告 姓名:徐缘(12122261)吴登明(12122262)徐亮(12122264)周天扬(12122265)  课程设计分工: 小结报告正文: 本次的大作业是...

    7年前    10374    0

    Visual FoxPro 课程设计实验报告

     中国最大的商务办公文档下载基地: http://www.word98.com/ ╔---------------------------------------------...

    7年前    11082    0

    《化工原理课程设计》报告换热器的设计

     《化工原理课程设计》报告 换热器的设计 目录 概述 1...

    1年前    581    0

    实验报告-电力电子课程设计

    掌握晶闸管仿真模型模块各参数的含义。理解晶闸管的特性。

    5个月前    273    0

    离散数学实验报告:建立关系矩阵实验

    建立关系矩阵实验的目的是理解并掌握关系的矩阵表示方法、为用序偶集合表示的关系建立相应的关系矩阵。学会用所学过的程序设计语言编程,解决关系矩阵的自动建立问题。实验的内容是用二维数组或向量存储关系矩...

    2年前    1176    0

    数据结构 第九章 查找

    .折半查找是否适合链表结构的序列,为什么?用二分查找的查找速度必然比线性查找的速度快,这种说法对吗?

    2年前    904    0

    招商细则N

    关于南京首届酒吧文化节招商细则 项目名称:南京市首届酒吧文化节 时 间: 2004年9月8日-10月7日 地 点:南京市 主 办:南京市旅游局 承 办:央际广...

    8年前    11543    0
    方案   旅游   宣传   招商   文化  

    票据管理流程控制矩阵

    票据管理流程控制矩阵 流程名称: 票据管理流程控制矩阵 流程目标: 经营目标: 提高经营过程票据使用的科学性、计划性。 充分利用企业信用,及时高效满足企...

    10年前    15066    0

    图3_7.战略矩阵

    弱 强 弱 强 实力 引力 弱 强 实力 引力 弱 强 实力 引力 本文档由香当网(https://www.xiangdang.net)用户上传

    7年前    28496    0
    战略  

    人生职业方向矩阵图

    人生职业方向矩阵图 人生职业方向矩阵图 个人优势及风险偏好 职业方向 资本金数量 经营管理/专业技能 风险偏好程度 少/无 低/无 低 公司低级员工 少/无 低...

    11年前    20073    0
    HR   个人   经营   投资   管理