学生成绩管理系统
二〇一四 年 六 月
软计
学生成绩管理系统
一、问题陈述
现有学生成绩信息文件1(1.txt),内容如下
姓名 学号 语文 数学 英语 张明明 01 67 78 82 李成友 02 78 91 88 张辉灿 03 68 82 56 王露 04 56 45 77 陈东明 05 67 38 47 …. .. .. .. … 学生成绩信息文件2(2.txt),内容如下:
姓名 学号 语文 数学 英语 陈果 31 57 68 82 李华明 32 88 90 68
张明东 33 48 42 56 李明国 34 50 45 87 陈道亮 35 47 58 77 …. .. .. .. … 试编写一管理系统,要求如下:
1)实现对两个文件数据进行合并,生成新文件3.txt。
2)抽取出三科成绩中有补考的学生并保存在一个新文件4.txt。
3)合并后的文件3.txt中的数据按总分降序排序(至少采用两种排序方法实现)。
4)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)。
5)要求使用结构体,链或数组等实现上述要求。 6)采用多种方法且算法正确者,可适当加分。
二、需求分析
本系统要求实现具体的五项功能,根据提供的这五项功能,运行时系统提供了相应的功能菜单,选择不同的选项来实现相应的功能。
1.采用了读文件和写文件的方式,边读边写,合并两个文件成为一个文件。 2.采用结构体数组存入从文件中读入的数据,再通过对于数据中的相关成绩判断该学生是否需要补考,如果需要补考则将其信息写入另外一个文件。
3.采用快速排序、选择排序、冒泡排序的方法按总分对学生数据进行排序。 4.采用了二种查找的方法找到学生信息并输出。 5.通过调用函数exit(0)退出程序。
三、概要设计
1、实现对文件1.txt和文件2.txt数据进行合并,生成新文件3.txt。 调用函数Unitedfile()来实现,函数以读的方式打开1.txt文件,以写的方式打开3.txt文件,从1.txt读入一个数据并写入3.txt文件,直到遇到1.txt
文件结束。关闭1.txt文件,再以读的方式打开2.txt文件,用上述方式直到遇到2.txt文件结束。关闭2.txt,3.txt文件。实现对于文件的合并。
2、抽取出三科成绩中有补考的学生并保存在一个新文件4.txt。
调用函数findout()来实现。函数以读的方式打开3.txt文件,以写的方式打开4.txt文件。读入3.txt文件的一个数据到结构体stud中,判断学生信息中语文、数学和英语成绩中是否有不及格的,如果有,则将数据写入4.txt中,直至遇到3.txt文件结束。
3、对合并后的文件3.txt中的数据按总分降序排序。
调用函数sortfile()来实现。函数提供了三种排序方法,通过调用函数kuaisu()来实现快速排序,通过调用函数xuanze()来实现选择排序,通过调用函数maopao()来实现冒泡排序。
4、输入一个学生姓名后,能查找到此学生的信息并输出结果。
调用函数findoutstudent()来实现。函数也提供了两种查找方法:
(1) 通过调用函数derectfindoutstudent()实现从文件从3.txt中逐
个读入数据,再进行查找判断,如果找到所需要的数据,则查找结束,否则继续查找直至文件结束。
(2) autofindoutstudent()在进行第三步的过程中,已经把3.txt中
的学生数据读入了结构体数组当中,调用函autofindoutstudent()直接从结构体中进行查找。
5、通过调用函数exit()退出。
main Unitedfile() findout() sortfile() findoutstudent() exit() Kuaisu() Xuanzhe() Maopao() derectfindoutstudent() autofindoutstudent()
四、详细设计
1.把1.txt和2.txt文件中的内容放到3.txt文件中。
调用Unitedfile()文件,打开文件1和文件3,从1.txt中读入学生数据进结构体,把结构体中学生数据放到文件3中。关闭文件1,从2.txt中读入学
生数据进结构体,把结构体中学生数据放到文件3中。关闭文件2和文件3。
void Unitedfile(){ fclose(fp); FILE *fp,*p; fp=fopen(\"d:\\\\2.txt\ Student stud; ; fp=fopen(\"d:\\\\1.txt\ while(fscanf(fp,\"%s%s%d%d; %d\
p=fopen(\"d:\\\\3.txt\ese,&stud.math,&stud.english )!= while(fscanf(fp,\"%s%s%d%dEOF) %d\ { ese,&stud.math,&stud.english )!= fprintf(p,\"%-6s %-6s %-6d EOF) %-6d %-6d\\n\
{ stud.chinese,stud.math,stud.engl fprintf(p,\"%-6s %-6s %-6d ish ); } %-6d %-6d\\n\ fclose(fp); stud.chinese,stud.math,stud.engl fclose(p); ish ); } }
2. 抽取出三科成绩中有分数低于60分的学生并保存在一个新文件4.txt
从3.txt中读入学生数据进结构体,判断是否有不及格的课程,如果有,则写入文件4.txt中
void findout(){ ish<60||stud.math<60) FILE *fp,*p; { Student stud; fprintf(p,\"%-6s %-6s %-6d fp=fopen(\"d:\\\\3.txt\%-6d %-6d\\n\; stud.chinese,stud.math,stud.engl
p=fopen(\"d:\\\\4.txt\ish ); } while(fscanf(fp,\"%s%s%d%d } %d\ fclose(fp); ese,&stud.math,&stud.english )!= fclose(p); EOF) }
{
if(stud.chinese<60||stud.engl
3.对文件3.txt中的数据按总分以降序进行排序(三种方法:选择排序、快速排序、冒泡排序)
void sortfile() { char c;
cout<<\"请选择排序方法:\"< xuanze();//选择排序 break; case'2': kuaisu();//快速排序 break; case'3': 3.1选择排序 void xuanze() { int j,k,max1,sum1,sum2,q; i=0; Student temp; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { i++;} fclose(fp); for(j=0;jstud[j].sum=stud[j].chinese +stud[j].math+stud[j].english; for(j=0;j sum1=stud[j].sum; for(k=j+1;ksum2=stud[k].sum; if(sum1 void kuaisu() { int i,low,high; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { maopao();//直接插入排序 break; }} { max1=k; sum1=sum2; } } if(max1!=j) { temp=stud[max1]; stud[max1]=stud[j]; stud[j]=temp; } stud[j].sum=sum1; } fp=fopen(\"d:\\\\3.txt\;//将排序后的数据写入3.txt中 for(q=0;qfprintf(fp,\"%-8s %-8s %-8d %-8d %-8d %-8d\\n\me,stud[q].id,stud[q].chinese,stud[q].math,stud[q].english,stud[q].sum ); } fclose(fp); } stud[i].sum=stud[i].chinese+stud[i].math+stud[i].english; i++; } fclose(fp); low=0; high=i-1; QSort(low,high);//快速排序 fp=fopen(\"d:\\\\3.txt\;//将排序后的数据写入3.txt中 for(int j=0;j{ fprintf(fp,\"%-8s %-8s %-8d %-8d %-8d %-8d\\n\me,stud[j].id,stud[j].chinese,st ud[j].math,stud[j].english,stud[j].sum ); } fclose(fp); } 3.3 冒泡排序 void maopao() { int j,k,q; Student temp; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { stud[i].sum=stud[i].chinese+stud[i].math+stud[i].english; i++; } int n=i; for( i=0;i k=j; } temp=stud[i]; stud[i]=stud[k]; stud[k]=temp; } fp=fopen(\"d:\\\\3.txt\将排序后的数据写入3.txt中 for(q=0;q } fclose(fp); } 4. 输入一个学生姓名后,能查找到此学生的信息并输出结果。 (1、从文件3中直接查找;2、在运行第三步的基本上查找) void findoutstudent()//提供两种查找方法 { char c; cout<<\"请选择查找方法\"< cout<<\"请输入学生姓名:\"; if(sign1==0&&c=='2') { cout<<\"请执行操作3 后再执行此项操作!\"< derectfindoutstudent();//从文件3中直接查找 break; case'2': autofindoutstudent();//从结构体数据中直接查找 break; } } 4.1从文件3中直接查找 void derectfindoutstudent(){ char NAME[30]; int flag=0; FILE *fp; fp=fopen(\"d:\\\\3.txt\; cin>>NAME; while(fscanf(fp,\"%s%s%d%d%d%dud[1].chinese,&stud[1].math,&stud[1].english,&stud[1].sum )!=EOF) { if(strcmp(stud[1].name,NAME)==0) { flag=1; cout<<\"*******姓名*******学号*******语文*******数学*******英语*******总分 *******\"< if(flag==0) cout<<\"无此学生相关信息\"< 4.2在运行第三步的基础上查找 void autofindoutstudent()//从结构体数组中查找 { int n,flag=0,k; char Name[30]; i=0; FILE *fp; fp=fopen(\"d:\\\\3.txt\; while(fscanf(fp,\"%s%s%d%d%d%dud[1].chinese,&stud[1].math,&stud[1].english,&stud[1].sum )!=EOF) { i++; } n=i-1; cin>>Name; for(k=1;k<=n;k++) { if(strcmp(stud[k].name,Name)==0) { flag=1; cout<<\"*******姓名*******学号*******语文*******数学*******英语*******总分*******\"< \"< if(flag==0) cout<<\"无此学生相关信息\"< 五、程序代码 #include char name[8]; char id[2]; int chinese; int math; int english; int sum; }Student; Student stud[SIZE]; int i; int sign=0,sign1=0,sign2=0,sign3=0; void Unitedfile() { FILE *fp,*p; Student stud; fp=fopen(\"d:\\\\1.txt\;//以读的方式打开1.txt p=fopen(\"d:\\\\3.txt\//以写的方式打开3.txt while(fscanf(fp,\"%s%s%d%d%d\ese,&stud.math,&stud.english )!=EOF) { fprintf(p,\"%-6s %-6s %-6d %-6d %-6d\\n\stud.chinese,stud.math,stud.english ); }//读取1.txt的数据进入结构体中,写入3.txt,继续读取直结束 fclose(fp);//关闭文件1.txt fp=fopen(\"d:\\\\2.txt\;//以写的方式打开2.txt while(fscanf(fp,\"%s%s%d%d%d\ese,&stud.math,&stud.english )!=EOF) { fprintf(p,\"%-6s %-6s %-6d %-6d %-6d\\n\stud.chinese,stud.math,stud.english ); } fclose(fp); fclose(p); } void findout(){ FILE *fp,*p; Student stud; fp=fopen(\"d:\\\\3.txt\; p=fopen(\"d:\\\\4.txt\ while(fscanf(fp,\"%s%s%d%d%d\ese,&stud.math,&stud.english )!=EOF) { if(stud.chinese<60||stud.english<60||stud.math<60) { fprintf(p,\"%-6s %-6s %-6d %-6d %-6d\\n\stud.chinese,stud.math,stud.english ); } } fclose(fp); fclose(p); } void xuanze() //对合并后的文件3.txt中的数据按总分降序排序 { int j,k,max1,sum1,sum2,q; i=0; Student temp; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { i++; }//从3.txt中读入数据进结构体数组stud中 fclose(fp); for(j=0;jstud[j].sum=stud[j].chinese +stud[j].math+stud[j].english; for(j=0;j sum1=stud[j].sum; for(k=j+1;ksum2=stud[k].sum; if(sum1 if(max1!=j) { temp=stud[max1]; stud[max1]=stud[j]; stud[j]=temp; } stud[j].sum=sum1; } fp=fopen(\"d:\\\\3.txt\;//将排序后的数据写入3.txt中 for(q=0;qfprintf(fp,\"%-8s %-8s %-8d %-8d %-8d %-8d\\n\me,stud[q].id,stud[q].chinese,stud[q].math,stud[q].english,stud[q].sum ); } fclose(fp); } void maopao() { int j,k,q; Student temp; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { stud[i].sum=stud[i].chinese+stud[i].math+stud[i].english; i++; } int n=i; for( i=0;i for(j=i+1;j k=j; } temp=stud[i]; stud[i]=stud[k]; stud[k]=temp; } fp=fopen(\"d:\\\\3.txt\将排序后的数据写入3.txt中 for(q=0;q } fclose(fp); } int Partition(int low,int high)//区分 { int p;//p是pivotkey初始关键字 Student temp; temp=stud[low]; p=stud[low].sum; while(low while(low stud[high]=stud[low]; } stud[low]=temp; return low; } void QSort(int low,int high)//快速排序 { int k; if(low void kuaisu()//读取文件,快速排序,将结果写入3.txt { int i,low,high; FILE *fp; fp=fopen(\"d:\\\\3.txt\; i=0; while(fscanf(fp,\"%s%s%d%d%d\d[i].chinese,&stud[i].math,&stud[i].english )!=EOF) { stud[i].sum=stud[i].chinese+stud[i].math+stud[i].english; i++; }//从文件3.txt中读入数据进结构体数组stud中 fclose(fp); low=0; high=i-1; QSort(low,high);//快速排序 fp=fopen(\"d:\\\\3.txt\;//将排序后的数据写入3.txt中 for(int j=0;jfprintf(fp,\"%-8s %-8s %-8d %-8d %-8d %-8d\\n\me,stud[j].id,stud[j].chinese,stud[j].math,stud[j].english,stud[j].sum ); } fclose(fp); } void derectfindoutstudent(){ char NAME[30]; int flag=0; FILE *fp; fp=fopen(\"d:\\\\3.txt\; cin>>NAME; while(fscanf(fp,\"%s%s%d%d%d%dud[1].chinese,&stud[1].math,&stud[1].english,&stud[1].sum )!=EOF) { if(strcmp(stud[1].name,NAME)==0) { flag=1; cout<<\"*******姓名*******学号*******语文*******数学*******英语*******总分*******\"< \"< if(sign1==0&&c=='2') { cout<<\"请执行操作3后再执行此项操作!\"< autofindoutstudent();//从结构体数据中直接查找 break; } } void sortfile()//提供两种排序方法 { char c; cout<<\"请选择排序方法:\"< switch(c) { case'1': xuanze();//选择排序 scanf(\"%d\ switch(choice) { break; case'2': kuaisu();//快速排序 break; case'3': maopao();//直接插入排 序 break; } } int main()/*主程序*/ { int choice; while(1) { /*主菜单*/ if(sign3==0) { printf(\"*******************************学生成绩管理系统*********************************\\n\"); printf(\"\1. 合并1.txt和2.txt为3.txt\\n\"); printf(\"\2. 抽取出三科成绩中有补考的学生并保存在一个新文件4.txt\\n\"); printf(\"\3. 对合并后的文件3.txt中的数据按总分降序排序\\n\"); printf(\"\4. 输入一个学生姓名,查找到此学生的信息并输出结果\\n\"); printf(\"\5. 退出\\n\"); printf(\"请选择(1-5):\\n\"); printf(\"********************************************************************************\\n\"); } sign3=1; case 1: Unitedfile(); sign=1; cout<<\"操作1成功!\"< if(sign==0) { cout<<\"请执行操作1后再执行此项操作!\"< cout<<\"操作2成功!\"< if(sign==0) { cout<<\"请执行操作1后再执行此项操作!\"< cout<<\"操作3成功!\"< while(1) { char c; findoutstudent(); cout<<\"继续查找请输入Y:\"< if(c=='N'||c=='n')break; } sign3=0; break; case 5: exit(0); break; } } return 0; } 六、运行结果与测试 七、设计体会与总结 通过本次课程设计,进一步熟悉了数据结构课程设计的基本设计思想,加深了对于数据结构的认识。本系统为学生成绩管理系统,能够用于基本的学生成绩管理。 在设计这个程序时,首先我们要弄清楚文件的存储,你是怎么把文件中的数据转移到另一个文件中去,之间的过程是什么样的。按照题目的要求一步一步下来。怎么抽取文件3中三科成绩中有补考的学生成绩到文件4中。在设计这个程序时,我遇到了很多困难,不知道文件是如何的进行存储的,怎么把其他文件中的数据传递到另个一文件中,两个文件能同时打开吧数据传递到第三个文件中去吗?怎么把文件中的数据调用到程序中来,被使用。在这次课程设计中,我发现写代码不是重要的,了解题目的意思,会设计程序框架才是最重要的。知道程序内部是怎么进行实现的才是设计程序的关键。如果没有以上的基本,根本学不出一个好的程序。 稀疏矩阵应用 一、问题陈述: 实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。 (1)稀疏矩阵的存储 (2)稀疏矩阵加法 (3)矩阵乘法 (4)矩阵转置 二、程序代码: #include typedef struct OLNode{ int i,j; int e; struct OLNode *right,*down; }OLNode,*OLink; typedef struct { int mu,nu,tu; OLink *rhead,*chead; }CrossList; //十字链表结构体定义 typedef struct{ int i,j; int e; }Triple; typedef struct{ Triple data[MAXSIZE]; int rpos[MAXSIZE + 1]; int nu,mu,tu; }TSMatrix; //三元组结构体定义; int CreateSMatix_OL(CrossList &M){ int i,j,e; OLink q; OLink p; printf(\"请输入稀疏矩阵的行数,列数,非零元素的个数:\"); scanf(\"%d%d%d\.tu); M.rhead=(OLink *)malloc((M.mu+1)*sizeof(OLNode)); M.chead=(OLink *)malloc((M.nu+1)*sizeof(OLNode)); for( i=1;i<=M.mu;i++) M.rhead[i]=NULL; for( i=1;i<=M.nu;i++) M.chead[i]=NULL; printf(\"请输入稀疏矩阵,如果行为0,则退出\\n\"); scanf(\"%d%d%d\ while(i!=0) { p=(OLink)malloc(sizeof(OLNode)); p->i=i;p->j=j;p->e=e; if(M.rhead[i]==NULL||M.rhead[i]->j>j) { p->right=M.rhead[i]; M.rhead[i]=p; } Else { q=M.rhead[i]; while(q->right&&q->right->j q=q->right; p->right=q->right; q->right=p; } if(M.chead[j]==NULL||M.chead[j]->i>i) { p->down=M.chead[j]; M.chead[j]=p; } else { q=M.chead[j]; while(q->down&&q->down->idown; p->down=q->down; q->down=p; } scanf(\"%d%d%d\ } return 0; }//创建十字链表 void CreateSMatrix(TSMatrix &M) { printf(\"请输入稀疏矩阵的行数、列数和非零元个数:\"); scanf(\"%d%d%d\.tu); if((M.mu<=0)||(M.nu<=0)||(M.tu<=0)||(M.tu>M.mu*M.nu)) printf(\"输入有误!\"); for(int i=1;i<=M.tu;i++)//输入稀疏矩阵元素 { printf(\"请输入元素坐标(所在行,所在列)及大小:\"); scanf(\"%d%d%d\M.data[i].j,&M.data[i].e); if((M.data[i].i<=0)||(M.data[i].j<=0)) { printf(\"输入错误,请重新输入\"); scanf(\"%d%d%d\M.data[i].j,&M.data[i].e); } } int num[100]; if(M.tu) { int i; for(i = 1; i <= M.mu; i++) num[i] = 0;//初始化 for(int t = 1; t <= M.tu; t++) ++num[M.data[t].i]; M.rpos[1] = 1; for(i = 2; i <= M.mu; i++) M.rpos[i] = M.rpos[i-1] + num[i-1]; } }//创建三元组 Void TransposeSMatrix(TSMatrix M,TSMatrix &T){ T.nu=M.mu; T.mu=M.nu; T.tu=M.tu; int q=1; for(int col=1;col<=M.nu;col++) for(int p=1;p<=M.tu;p++) if(M.data[p].j==col) { T.data[q].i=M.data[p].j; T.data[q].j=M.data[p].i; T.data[q].e=M.data[p].e; q++; } }//三元组转置 int Compare(int a1,int b1,int a2,int b2) { if(a1>a2) return 1; else if(a1 return 0; } void AddTMatix(TSMatrix M,TSMatrix T,TSMatrix &S) { S.mu=M.mu>T.mu?M.mu:T.mu;//对S矩阵的行数赋值 S.nu=M.nu>T.nu?M.nu:T.nu;//对S矩阵的列数赋值 S.tu=0; int ce; int q=1;int mcount=1,tcount=1; while(mcount<=M.tu&&tcount<=T.tu) { switch(Compare(M.data[mcount].i,M.data[mcount].j,T.data[tcount].i,T.data[tcount].j)) { case -1: S.data[q].e=M.data[mcount].e;//当 if(M.data[mcount].i case 1: S.data[q].e=T.data[tcount].e; if(M.data[mcount].i>T.data[tcount].i||M.data[mcount].j>T.data[tcount].j) S.data[q].i=T.data[tcount].i; S.data[q].j=T.data[tcount].j;//把第二个矩阵的行数i,列数j赋值给S矩阵的行数i,列数j q++; tcount++; break; case 0: ce=M.data[mcount].e+T.data[tcount].e; if(ce) { S.data[q].e=ce; S.data[q].i=M.data[mcount].i; S.data[q].j=M.data[mcount].j; q++; mcount++; tcount++; } else { mcount++; tcount++; } break; } }; while(mcount<=M.tu) { S.data[q].e=M.data[mcount].e; S.data[q].i=M.data[mcount].i; S.data[q].j=M.data[mcount].j; q++; mcount++; }//在case=-1的情况下对S矩阵的非零值,行数,列数进行赋值 while(tcount<=M.tu) { S.data[q].e=T.data[tcount].e; S.data[q].i=T.data[tcount].i; S.data[q].j=T.data[tcount].j; q++; tcount++; }//在case=1的情况下对S矩阵的非零值,行数,列数进行赋值 S.tu=q-1; }//三元组相加 int MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) { int arow, brow, ccol, i, t, ctemp[100], p, q, tp; if(M.nu != N.mu) return 0; Q.mu = M.mu, Q.nu = N.nu, Q.tu = 0; if(M.tu * N.tu != 0) { for(arow = 1; arow <= M.mu; ++arow) { for(i = 0; i <= N.nu; ++i) ctemp[i] = 0; Q.rpos[arow] = Q.tu + 1; if(arow < M.mu) tp = M.rpos[arow + 1]; else tp = M.tu +1; for(p = M.rpos[arow]; p < tp; ++p)//把每行与每列相乘 { brow = M.data[p].j; if(brow < N.mu) t=N.rpos[brow+1]; else t = N.tu + 1; for(q = N.rpos[brow]; q < t; ++q) { ccol = N.data[q].j; ctemp[ccol] += M.data[p].e * N.data[q].e; } } for(ccol = 1; ccol <= Q.nu; ++ccol) { if(ctemp[ccol]) { if(++(Q.tu) > MAXSIZE) return 1; Q.data[Q.tu].i = arow; Q.data[Q.tu].j = ccol; Q.data[Q.tu].e = ctemp[ccol]; } } }} return 1; }//三元组相乘 void ShowTMatrix(TSMatrix M) { for(int col=1;col<=M.mu;col++)//通过双重循环,把稀疏矩阵中不为零的元素的行数、列数和值显示出来 for(int p=1;p<=M.tu;p++) if(M.data[p].i==col) printf(\"%4d%4d%4d\\n\,M.data[p].j,M.data[p].e); }//三元组显示 void TurnSMatrix_OL(CrossList &M){ int col,row; //定义循环变量 OLink p,q; for(col=1;col<=M.mu;col++) { q=p=M.rhead[col]; while(q) { row=p->i; p->i=p->j; p->j=row; q=p->right; p->right=p->down; p->down=q; } }}//十字链表转置 int SMatrix_ADD(CrossList *A,CrossList *B){ OLNode *pa,*pb,*pre,*p,*cp[100]; int i,j,t; t=A->tu+B->tu; for(j=1;j<=A->nu;j++) cp[j]=A->chead[j];//将A矩阵的列表头指针赋给cp数组 for(i=1;i<=A->mu;i++) { pa=A->rhead[i]; pb=B->rhead[i];//将A,B矩阵的行表头指针分别赋给pa,pb pre=NULL; while(pb) {//当pb不等于零 if(pa==NULL||pa->j>pb->j) { p=(OLink)malloc(sizeof(OLNode));//给p动态分配空间 if(!pre)A->rhead[i]=p; else pre->right=p; p->right=pa; pre=p; p->i=i;p->j=pb->j;p->e=pb->e; if(!A->chead[p->j]){ A->chead[p->j]=cp[p->j]=p; p->down=NULL; }//如果A->chead[p->j]不等于零,则把p赋给它及cp[p->j] else { cp[p->j]->down=p; cp[p->j]=p; } pb=pb->right; } cp[p->j] else if(pa->j pre=pa; pa=pa->right; } else if(pa->e+pb->e) { t--; pa->e+=pb->e; pre=pa; pa=pa->right; pb=pb->right; } else { t=t-2; if(!pre) A->rhead[i]=pa->right; else pre->right=pa->right; p=pa;pa=pa->right; if(A->chead[p->j]==p) A->chead[p->j]=cp[p->j]=p->down; else cp[p->j]->down=p->down; free(p); pb=pb->right; } } } A->mu=A->mu>B->mu?A->mu:B->mu; A->nu=A->nu>B->nu?A->nu:B->nu; return 1; }//十字链表相加 int MultSMatrix_OL(CrossList M, CrossList N, CrossList &Q) { int i, j, e; //中间变量 OLink p0, q0, p, pl, pla; //中间变量 if(M.nu != N.mu) //检查稀疏矩阵M的列数和N的行数是否对应相等 { printf ( \"稀疏矩阵A的列数和B的行数不相等,不能相乘。\\n\" ); return 0; } Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; if(!(Q.rhead = (OLink *)malloc((Q.mu + 1) * sizeof(OLink)))) exit(-2); if(!(Q.chead = (OLink *)malloc((Q.nu + 1) * sizeof(OLink)))) exit(-2); for( i =1; i <= Q.mu; i++) Q.rhead[i] = NULL; for( i = 1; i <= Q.nu; i++) Q.chead[i] = NULL; for( i=1;i<=Q.mu;i++) for( j=1;j<=Q.nu;j++) { p0=M.rhead[i]; q0 = N.chead[j]; e = 0; while(p0 && q0) //M第i行和N第j列有元素 {if( p0->j > q0->i) q0 = q0->down; else if(p0->j < q0->i) p0 = p0->right; else { e += p0->e * q0->e; //乘积累加 q0 = q0->down; p0 = p0->right; //移动指针 } } if(e) //乘积不为 { if(!(p = (OLink)malloc(sizeof(OLNode)))) exit(-2); Q.tu++;//非零元素增加 p->i = i; p->j = j;p->e = e; p->right = NULL;p->down = NULL; if(Q.rhead[i] == NULL) //若p为该行的第个结点 Q.rhead[i] = pl = p; else pl->right = p, pl = p; //插在pl所指结点之后,pl右移 //列插入 if(Q.chead[j] == NULL) //若p为该列的第一个结点 Q.chead[j] = p; //该列的表头指向p else {//插在列表尾 pla = Q.chead[j];//pla指向j行的第个结点 while(pla->down) pla = pla->down;//pla指向j行最后一个结点 pla->down = p; }}} return 1; }//十字链表相乘 int ShowMAtrix(CrossList *A) { int col; OLink p; for(col=1;col<=A->mu;col++) if(A->rhead[col]){p=A->rhead[col]; while(p) { printf(\"%3d%3d%3d\\n\j,p->e);p=p->right;} } return 1; }//十字链表显示 void main(){ int n,i; TSMatrix M,T,S; CrossList MM,TT,SS; printf(\" ***稀疏矩阵应用***\"); printf(\"\\n请你选择创建稀疏矩阵的方法:\\n1:用三元组创建稀疏矩阵\\n2:用十字链表创建稀疏矩阵\\n3:退出程序\"); printf(\"\\n\"); scanf(\"%d\ switch(n){ case 1: CreateSMatrix(M); printf(\"您输入的稀疏矩阵为(只列出非零元素):\\n 行 列 大小\\n\"); ShowTMatrix(M); printf(\"已经选择三元组创建稀疏矩阵,请选择操作:\\n1:稀疏矩阵转置\\n2:稀疏矩阵相加\\n3:稀疏矩阵相乘\\n4:退出程序\\n\"); scanf(\"%d\ switch(i){ case 1:TransposeSMatrix(M,T); printf(\"转置后的矩阵为 (只列出非零元素):\\n 行 列 大小\\n\"); ShowTMatrix(T); break; case 2:printf(\"请你输入另一个稀疏矩阵:\"); CreateSMatrix(T); AddTMatix(M,T,S); printf(\"相加后的矩阵为(只列出非零元素):\\n 行 列 大小\\n\"); ShowTMatrix(S); break; case 3:printf(\"请你输入另一个稀疏矩阵:\"); CreateSMatrix(T); MultSMatrix(M,T,S); printf(\"相乘后的矩(只列出非零元素):\\n 行 列 大小\\n\"); ShowTMatrix(S); break; case 4: exit(0); };break; case 2: { CreateSMatix_OL(MM); printf(\"您输入的稀疏矩阵为(只列出非零元素):\\n 行 列大小\\n\"); ShowMAtrix(&MM); printf(\"已经选择十字链表创建稀疏矩阵,请选择操作:\\n1:稀疏矩阵转置\\n2:稀疏矩阵相加\\n3:稀疏矩阵相乘\\n4:退出程序\\n\"); scanf(\"%d\ switch(i) { case 1: 三、运行结果: 三元组创建稀疏矩阵 输入稀疏矩阵: TurnSMatrix_OL(MM); printf(\"转置后的矩阵为(只列出非零元素):\\n 行 列大小\\n\"); ShowMAtrix(&MM); break; case 2: printf(\"请你输入另一个稀疏矩阵:\"); CreateSMatix_OL(TT); SMatrix_ADD(&MM,&TT); printf(\"相加后的矩阵为(只列出非零元素):\\n 行 列大小\\n\"); ShowMAtrix(&MM);break; case 3:printf(\"请你输入另一个稀疏矩阵:\"); CreateSMatix_OL(TT); MultSMatrix_OL(MM,TT,SS); printf(\"相乘后的矩阵为(只列出非零元素):\\n 行 列大小\\n\"); ShowMAtrix(&SS);break; case 4:exit(0); } };break; case 3:exit(0); default :printf(\"erorr\"); } } 稀疏矩阵转置 两个稀疏矩阵相加: 两个稀疏矩阵相乘: 用十字链表创建稀疏矩阵 稀疏矩阵转置: 稀疏矩阵相加 稀疏矩阵相乘 四、设计体会与总结 在这次课程设计中让我感受最深的是,不要急着动手,要先进行分析,架好整个框架,在开始代码的编写。 在设计这个题目时,刚开始我很迷茫,不知道怎么去做,该怎么去做这个程序设计。我在网上收索相关的内容。然后我开始根据收索到的相关知识对该题目进行分析,在做题之前,我们要弄懂什么是稀疏矩阵,稀疏矩阵的相关概念。然后就是三元组存储。三元组是什么?三元组可以看成是一个三维的数组里面可以放稀疏矩阵的行值、列值、非零元素的值。十字链表是这个程序设计中最烦的地方。因为十字链表的概念,不清楚,不知道数据是怎么存储的,怎么样对数据进行改变如进行转置等操作。在程序设计前不要急着写代码,首先要弄懂整个题目的意思,然后进行需求分析。在进行完分析后,在把整个程序分成多个模块,逐个模块段去进行编程,然后合成一个完成的程序。最后在进行调试运行。 因篇幅问题不能全部显示,请点此查看更多更全内容