中国石油大学(北京)远程教育学院
期 末 考 试
《数据结构课程设计》
学习中心:_______ 姓名:________ 学号:_______ 关于课程考试违规作弊的说明 1、提交文件中涉嫌抄袭内容(包括抄袭网上、书籍、报刊杂志及其他已有论文),带有明显外校标记,不符合学院要求或学生本人情况,或存在查明出处的内容或其他可疑字样者,判为抄袭,成绩为“0”。 2、两人或两人以上答题内容或用语有50%以上相同者判为雷同,成绩为“0”。 3、所提交试卷或材料没有对老师题目进行作答或提交内容与该课程要求完全不相干者,认定为“白卷”或“错卷”,成绩为“0”。 1.课程设计题目 从下面两道题目中任选一题完成。 1.1 高校考试报名系统 高校考试报名给教务管理部门增加了很大的工作量,报名数据手工录入既费时又会不可避免地出现错误,同时也给不少学生以可乘之机。本项目是对考试报名管理的简单模拟,用菜单选择方式完成下列功能: (1)输入考生信息,每条考生信息由准考证号(五位数字组成)、姓名、性别、年龄、报考科目等信息组成; (2)输出考生信息; (3)查询考生信息; (4)添加考生信息; (5)修改考生信息; (6)删除考生信息; (7)对考试信息按照准考证号进行排序。 要求:界面友好,每步给出适当的操作提示,并且系统具有一定的容错能力。 1.2北京景点查询系统 在旅游景区,经常会遇到游客打听从一个景点到另一个景点的最短路径和最短距离,这类游客不喜欢按照导游图的线路来游览,而是挑选自己感兴趣的景点游览。为于帮助这类游客信息查询,就需要计算出所有景点之间最短路径和最短距离。建立北京景区旅游信息管理系统,实现的主要功能包括制订旅游景点导游线路策略和制订景区道路铺设策略。具体实现的功能模块如下: (1)创建景区景点分布图,要求至少分布图中至少有10个景点; (2)输出景区景点分布图,用邻接矩阵表示; (3)输出从某点开始的导游线路图; (4)判断导游线路图有无回路; (5)求两个景点间的最短路径和最短距离; (6)输出道路修建规划图。 要求主程序用菜单选项供用户选择功能模块,界面友好,每步给出适当的操作提示,系统具有一定的容错能力。 2.课程设计报告书写规范 优学100f(www.youxue100f.com) 课程设计报告包括该题目的需求分析、概要设计、详细设计、程序测试、感想与体会几部分内容。下面以“稀疏矩阵运算器”为例说明如何写课程设计报告。 题目要求:设计一个稀疏矩阵计算器,实现两个稀疏矩阵的加法、减法、乘法以及矩阵的转置运算。采用菜单为应用程序的界面,用户通过对菜单进行选择,分别实现矩阵的相加、相减、相乘以及矩阵转速运算。 2.1需求分析 1. 稀疏矩阵是指稀疏因子小于等于0.5的矩阵。利用“稀疏”特点进行存储和计算可以大大节省存储空间,提高计算效率。实现一个能进行稀疏矩阵基本运算的运算器。 2. 以“带行逻辑链接信息”的三元组顺序表表示稀疏矩阵,实现矩阵转置,以及两个矩阵的加、减、乘的运算。稀疏矩阵的输入形式采用三元组表示,运算结果以阵列形式列出。 3. 演示程序以用户和计算机的对话方式进行,数组的建立方式为边输入边建立。首先输入矩阵的行数和列数,并判别给出的两个矩阵的行列数是否与所要求的运算相匹配。 4. 程序可以对三元组的输入属性不加以限制;根据对矩阵的行列,三元组作之间插入排序,从而进行运算时,不会产生错误。 5. 在用三元组表示稀疏矩阵时,相加、相减和相乘所产生的结果矩阵另外生成。 6. 运行环境:VC6.0++。 2.2概要设计 稀疏矩阵元素用三元组表示: typedef struct{ int i; //非零元的行下标 int j; //非零元的列下标 int e; //矩阵非零元 }Triple; 稀疏矩阵采用三元组顺序表存储: #define MSXSIZE 12500 //假设非零元个数的最大值为200 #define MAXRC 10 //假定矩阵的最大行数为10 typedef struct { int mu ; //矩阵的行数 int nu ; //矩阵的列数 int tu ; //矩阵的非零元素个数 Triple data[MAXSIZE+1]; //非零元三元组表,data[0]没有用 int rpos[MAXRC+1]; //各行第一个非零元素的位置表 }Tabletype; 系统主要函数及功能如下: Menu( ):主控菜单,接收用户的选项; Input_Matrix( ):输入矩阵; Print_matrix( ):输出矩阵; Cal_matrix( ):计算矩阵每行第一个非零元在三元组中的位序号; TransposeMatrix( ):矩阵转置; Add_Matrix( ):矩阵加法运算; Sub_Matrix( ):矩阵减法运算; Multi_Matrix( ):矩阵乘法运算。 模块的调用关系如图1所示。 图1 程序调用模块示意图 2.3详细设计 1. 主函数设计 //***************************************** //* 矩阵运算主函数 * //***************************************** 主函数中,实现用户菜单菜单的打印,并根据用户的选项执行相应的功能,主函数力求简洁、清晰。 void main( ) { num=Menu(); //打印主菜单 while(num) { switch(num) { case 1: Multi_Matrix(); //矩阵相乘 break; case 2: TransposeMatrix(); //矩阵转置 break; case 3: Add_Matrix(); //矩阵加法 break; case 4: Sub_Matrix(); //矩阵减法 case 0: break; }//switch num=Menu(); }//while } 2. 主菜单设计 主控菜单是用来输出提示信息和处理输入,此函数返回用户的选项,提供给main函数中的switch语句。对于不符合要求的选项,提示输入错误并要求用户重新输入。将此函数与main函数合在一起,编译运行程序,即可检查并验证菜单选项是否正确。 主菜单如下: //***************************************** //* 打印主控菜单函数 * //***************************************** int menu( ) { printf("\n 主菜单"); printf("\n*********************"); printf("\n 1. 矩阵乘法"); printf("\n 2. 矩阵转置"); printf("\n 3. 矩阵加法"); printf("\n 4. 矩阵减法"); printf("\n 0. 退出"); printf("\n*********************"); scanf("%d",&num); while(num<0||num>4) //输入非法,重新输入 scanf("%d",&num); return num; } 3. 矩阵乘法运算函数 //***************************************** //* 矩阵乘法运算算法 * //***************************************** Status Multi_Matrix() { Input_Matrix(&a); //输入矩阵a Input_Matrix(&b); //输入矩阵b Cal_matrix(&a); //计算矩阵a每行第一个非零元的位序号 Cal_matrix(&b); //计算矩阵b每行第一个非零元的位序号 if (a.nu!=b.mu) //不符合矩阵乘法条件,不能相乘 return ERROR; c.mu=a.mu; //对矩阵c初始化 c.nu=b.nu; c.tu=0; if(a.tu*b.tu!=0){ for(arow=1;arow<=a.mu;arow++){ /*处理矩阵a的每一行*/ for (p=1;p< MAXRC+1;p++) /*当前行各元素累加器清零*/ ctemp[p]=0; c.rpos[arow]=c.tu+1; if(arow<a.mu ) tp=a.rpos [arow+1]; else tp=a.tu +1; for(p=a.rpos[arow]; p<tp;p++){ //求得c中第crow行的非零元 brow=a.data[p].j; if(brow<b.nu) t=b.rpos[brow+1]; else t=b.tu+1; for (q=b.rpos[brow];q<t;q++){ ccol=b.data[q].j; /*乘积元素在矩阵c中的列号*/ ctemp[ccol]+=a.data[p].e*b.data[q].e; } /*for q*/ }//for p for(ccol=1;ccol<=c.nu;ccol++) if(ctemp[ccol]) /*压缩存储该行非零元*/ { if((c.tu)>MAXSIZE) exit(1); c.tu++; c.data[c.tu].i=arow; c.data[c.tu].j=ccol; c.data[c.tu].e=ctemp[ccol]; }/*end if*/ }/*for arrow*/ }/*if*/ Print_matrix(a); Print_matrix(b); Print_matrix(c); } 4. 矩阵转置算法 //***************************************** //* 矩阵转置算法 * //***************************************** void TransposeMatrix(){ Input_Matrix(&a); //输入矩阵a b.mu=a.nu; b.nu=a.mu; b.tu=a.tu; if(b.tu){ q=1; /*b.data的下标*/ for(col=1;col<=a.nu;col++) //对a的每一列 for(p=1;p<=a.tu;p++) /*p为a的下标*/ if( a.data[p].j==col){ //寻找矩阵a中列为col的非零元 b.data[q].i=a.data[p].j; b.data[q].j=a.data[p].i; b.data[q].e=a.data[p].e; q++; }//if(p) }//if(b.tu) Print_matrix(b); //输出a的转置矩阵 } 5. 矩阵加法算法 //***************************************** //* 矩阵加法运算函数 * //* c=a+b * //***************************************** Status Add_Matrix(){ Input_Matrix(&a); //输入矩阵a Input_Matrix(&b); //输入矩阵b if(a.mu !=b.mu ||a.nu !=b.nu ) //不满足矩阵加法条件 return ERROR; c.mu =a.mu ; c.nu =a.nu ; ta=1; tb=1; tc=1; if(a.tu *b.tu !=0){ while((ta<=a.tu) && (tb<=b.tu)){ if(a.data[ta].i==b.data[tb].i){ if(a.data[ta].j==b.data[tb].j){ temp=a.data[ta].e+b.data[tb].e; if(temp!=0){ c.data[tc].i=a.data[ta].i; c.data[tc].j=a.data[ta].j; c.data[tc].e=temp; tc++; }//end if (temp) ta++; tb++; }//end if else{ if(a.data[ta].j<b.data[tb].j){ c.data[tc].i=a.data[ta].i; c.data[tc].j=a.data[ta].j; c.data[tc].e=a.data[ta].e; ta++; tc++; }//end of else if else{ c.data[tc].i=b.data[tb].i; c.data[tc].j=b.data[tb].j; c.data[tc].e=b.data[tb].e; tb++; tc++; }// } }//end if else{ if(a.data[ta].i<b.data[tb].i){ c.data[tc].i=a.data[ta].i; c.data[tc].j=a.data[ta].j; c.data[tc].e=a.data[ta].e; tc++; ta++; } else{ c.data[tc].i=b.data[tb].i; c.data[tc].j=b.data[tb].j; c.data[tc].e=b.data[tb].e; tc++; tb++; } } }//while while(ta<=a.tu){ //处理a中剩余非零元 c.data[tc].i=a.data[ta].i; c.data[tc].j=a.data[ta].j; c.data[tc].e=a.data[ta].e; tc++; ta++; } while(tb<=b.tu){ //处理b中剩余非零元 c.data[tc].i=b.data[tb].i; c.data[tc].j=b.data[tb].j; c.data[tc].e=b.data[tb].e; tc++; tb++; } }// c.tu=tc; Print_matrix(c); } 6. 矩阵输入算法 用于输入矩阵的行数、列数、非零元个数,以及每个非零元素。输入算法如下: //***************************************** //* 矩阵输入算法 * //***************************************** Status Input_Matrix(Tabletype *t) { scanf(t->mu, t->nu, t->tu); //获得矩阵行列数、非零元个数 for(i=1;i<=tu;i++) scanf(t->data [i].i, t->data [i].j,t->data [i].e); return OK; } 7. 矩阵输出算法 将三元组以矩阵方式输出在屏幕上,算法如下: //***************************************** //* 矩阵输出函数 * //***************************************** Status Print_matrix(Tabletype m){ k=1; for(i=1;i<=m.mu;i++){ for(j=1;j<=m.nu ;j++) {/*非零元素*/ if((m.data[k].i==i)&&(m.data[k].j==j)){ printf(m.data[k].e); k++; } else printf(“0”); /*零元素*/ } printf("\n"); } } 8. Cal_matrix函数 在矩阵乘法运算时,需要统计矩阵每行第一个非零元在三元组表中的位序号,算法如下: void cal_matrix(Tabletype *m){ //计算矩阵中每一行中第一个非零元的位序号 for(row=1;row<=m->mu ;row++) num[row]=0; for(t=1;t<=m->tu ;t++) num[m->data [t].i]++; m->rpos [1]=1; for(row=2;row<=m->mu ;row++) m->rpos [row]=m->rpos [row-1]+num[row-1]; } 2.4程序测试 在这部分给出程序运行结果的屏幕截图,以及测试分析。 2.5感想与体会 这部分给出算法设计过程中的问题、程序调试过程的问题与收获。 3.要求 源程序没有语法错误,运行结果正确; 设计报告按照规范书写。 课程设计最后提交内容包括:源程序与课程设计报告。 |