数据结构课程设计报告书教学计划编制问题.docx
《数据结构课程设计报告书教学计划编制问题.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告书教学计划编制问题.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构课程设计报告书教学计划编制问题
数据结构课程设计报告书
教学计划编制问题
题目:
制定教学计划
1.内容摘要
摘要:
首先利用拓扑排序对课程先后顺序进行分析,邻接表为主要存储结构,栈为主要辅助结构。
给出课程的先后关系,即AOV网,然后进行拓扑排序,但当有向图中存在环时,无法查找该图的一个拓扑排序。
当图中所有定点全部输出,表示对该图排序成功。
实现拓扑排序算法时,相应的建立邻接表存储AOV网。
为了避免重复检测入度为零的顶点,建立一个栈来对入度为零的点进行存放。
根据课程先后关系,对各个学期的课程进行拓扑排序,输出。
2.索引关键词
关键词:
邻接表存储,栈的应用,拓扑排序。
1.题目要求及设计要求------------------------------------------1
2.系统完成功能及功能框图-----------------------------------2—4
3.核心算法及说明------------------------------------------5—21
4.运行及测试结论-----------------------------------------22—23
5.参考资料--------------------------------------------------23
6.后记-------------------------------------------------------23
第一部分:
课程设计题目要求
1.1课程设计目的
大学的每个专业都要制定教学计划。
假设任何专业都有固定的学习年限,每学年含两学期,每学期的时间长度和学分上限值均相等。
每个专业开设的课程都是确定的,而且课程在开设时间的安排必须满足先修关系。
每门课程有哪些先修课程是确定的,可以有任意多门,也可以没有。
每门课恰好占一个学期。
在这样的前提下设计一个教学计划编制程序。
1.2课程设计的实验环境
硬件要求能运行Windows9.X操作系统的微机系统。
软件:
MicrosoftVisualC++6.0
第二部分:
设计要求
1.输入参数包括:
学期总数,一学期的学分上限,每门课的课程号(固定占3位的字母数字串)学分和直接先修课的课程号。
2.允许用户指定下列两种编排策略之一:
一是使学生在各学期中的学习负担尽量均匀;二是使课程尽可能地集中在前几个学期中。
3.若根据给定的条件问题无解,则报告适当的信息;否则将教学计划输出到用户指定的文件中。
计划的表格格式自行设计。
测试数据:
学期总数:
6
学分上限:
10
该专业共开设12门课,课程号从C1--C12
学分顺序为2,3,4,3,2,3,4,4,7,5,2,3
第三部分:
系统完成功能及功能框图
图1:
某专业的学生必须学习的课程
图2:
表示课程之间优先关系的有向图
0
C1
1
C2
2
C3
3
C4
4
C5
5
C6
6
C7
^
7
C8
^
8
C9
9
C10
10
C11
11
C12
^
图3:
邻接表
第四部分:
详细设计
1.程序主要包括五个模块
1)、图的邻接表的存储表示,即结构体的定义
typedefcharVertexType[MAX_NAME];
typedefstructArcNode
{
intadjvex; //该弧所指向的顶点的位置
structArcNode*nextarc; //指向下一条弧的指针
}ArcNode; //链表结点
typedefstruct //链接表
{
VertexTypedata; //顶点信息
intgrades; //存储学分信息
ArcNode*firstarc; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM]; //头结点
typedefstruct
{
AdjListvertices; //vertices存储课程名
intvexnum,arcnum; //图的当前顶点数和边数
}ALGraph;
2)、利用前插法,建立图的邻接链表
printf("请输入下列课程的先修课程(无先修课程输入0结束后也输入0)\n");
for(k=0;k{
printf("%s的先修课程:
",G.vertices[k].data);
scanf("%s",va);
while(va[0]!
='0')
{
i=LocateVex(G,va);//弧头
j=k; //弧尾
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->nextarc=G.vertices[i].firstarc;//插在表头
G.vertices[i].firstarc=p;
scanf("%s",va);
}
}
3)、输出图的顶点和边
printf("%d个顶点",G.vexnum);
for(i=0;iprintf("%4s",G.vertices[i].data);
printf("\n%d条弧边:
\n",G.arcnum);
for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{
printf("%s--->%s\n",G.vertices[i].data,G.vertices[p->adjvex].data);
p=p->nextarc;
}
}
4)、通过栈实现拓扑排序
FindInDegree(G,indegree); //对各顶点求入度
InitStack(S); //初始化栈
for(i=0;iif(!
indegree[i])Push(S,i); //入度为0者进栈
count=0; //对输出顶点计数
while(!
StackEmpty(S))
{
Pop(S,i);
printf("%s(%d分),",G.vertices[i].data,G.vertices[i].grades);
Temp[j++]=G.vertices[i]; //将当前的拓扑序列保存起来
++count; //输出i号顶点并计数
for(p=G.vertices[i].firstarc;p;p=p->nextarc)//对i号顶点的每个邻接点的入度减1
{
k=p->adjvex;
if(!
(--indegree[k]))//若入度减为0,则入栈
Push(S,k);
}
}
if(count{
printf("此有向图有回路无法完成拓扑排序");
returnERROR;
}
elseprintf(" 为一个拓扑序列");
printf("\n");
ReturnOK
ReturnERROR
依次将入度为0的顶点存入InDegree中
对每个顶点求入度,并存入数组InDegree[i]中(i=0…n)
初始化栈Stack,Counter=0
对以i号顶点为尾弧的每个邻接点的入度减1,并将入度减1后为零的顶点号压入栈中,输出i,计数器加1(Counter++)
推出栈顶的一个元素(入度为零的顶点号)至i,输出i,计数器加1(Counter++)
堆栈是否为空?
n个顶点全输出
依次将入度为0的顶点存入InDegree中
NY
YN
5)、解决问题
根据学分上限决定出每学期应学课程,其中Temp[]中存储的是经过拓扑排序后的课程先后顺序。
intq=1,Z=0;
while(q<=TotalTerms)
{
intC=Temp[Z].grades;
printf("第%d个学期应学课程:
",q);
while(C<=MaxScores)
{
C=C+Temp[Z+1].grades;
if(Z++Z;
}
printf("\n");
if(q==TotalTerms)printf("课程编制完成!
");
q++;
}
2.主要设计程序如下:
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineMAX_NAME3
#defineMAXCLASS100//顶点字符串的最大长度
#defineMAX_VERTEX_NUM100//最大顶点数
#defineN12
typedefcharVertexType[MAX_NAME];
intTotalTerms;//学期总数
intMaxScores;//学分上限
/*----图的邻接表存储表示----*/
typedefstructArcNode
{
intadjvex;//该弧所指向的顶点的位置弧的节点结构
structArcNode*nextarc;//指向下一条弧的指针
}ArcNode;//链表结点
typedefstruct//链接表
{
VertexTypedata;//顶点信息
intgrades;//存储学分信息
ArcNode*firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];//头结点
typedefstruct
{
AdjListvertices;//vertices存储课程名
intvexnum,arcnum;//图的当前顶点数和弧数
}ALGraph;
voidOUTPUT()
{
ints;
printf("\t\t教学计划编制菜单\n");
printf("\t\t课程代码|课程名称|优先课程\n");
printf("\t\tC1|程序设计基础|无\n");
printf("\t\tC2|离散数学|C1\n");
printf("\t\tC3|数据结构|C1,C2\n");
printf("\t\tC4|汇编语言|C1\n");
printf("\t\tC5|语言的设计和分析|C3,C4\n");
printf("\t\tC6|计算机原理|C11\n");
printf("\t\tC7|编译原理|C5,C3\n");
printf("\t\tC8|操作系统|C3,C6\n");
printf("\t\tC9|高等数学|无\n");
printf("\t\tC10|线性代数|C9\n");
printf("\t\tC11|普通物理|C9\n");
printf("\t\tC12|数值分析|C9,C10,C1\n");
printf("pressanynumkeytocontinue:
");
scanf("%d",&s);
}
/*查找图中某个顶点位置*/
intLocateVex(ALGraphG,VertexTypeu)
{
inti;
for(i=0;iif(strcmp(u,G.vertices[i].data)==0)
returni;
return-1;
}
{
i=LocateVex(G,va);//弧头
j=k;//弧尾
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->nextarc=G.vertices[i].firstarc;//插在表头
G.vertices[i].firstarc=p;
scanf("%s",va);
}
}
returnOK;
}
/*输出图G的信息*/
voidDisplay(ALGraphG)
{
inti;
ArcNode*p;
printf("有向图\n");
printf("%d个顶点",G.vexnum);
for(i=0;iprintf("%4s",G.vertices[i].data);
printf("\n%d条弧边:
\n",G.arcnum);
for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{
printf("%s--->%s\n",G.vertices[i].data,G.vertices[p->adjvex].data);
p=p->nextarc;
}
}
}
/*求顶点的入度*/
voidFindInDegree(ALGraphG,intindegree[])
{
inti;
ArcNode*p;
for(i=0;ifor(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{
indegree[p->adjvex]++;
p=p->nextarc;
}
}
}
structName
{
charc[20];
}name;
/*栈定义*/
typedefintSElemType;//栈类型
#defineStack_NUM20//存储空间初始分配量
#defineStack_MoreNUM5//存储空间分配增量
typedefstructSqStack
{
SElemType*base;
SElemType*top;
intstacksize;//分配的存储空间
}SqStack;
/*栈的初始化*/
intInitStack(SqStack&S)
{
S.base=(SElemType*)malloc(Stack_NUM*sizeof(SElemType));
if(!
S.base)
exit(-1);
S.top=S.base;
S.stacksize=Stack_NUM;
returnOK;
}
/*判空*/
intStackEmpty(SqStackS)
{
if(S.top==S.base)
returnTRUE;
else
returnFALSE;
}
/*出栈*/
intPop(SqStack&S,SElemType&e)
{
if(S.top==S.base)
returnERROR;
e=*--S.top;
returnOK;
}
/*入栈*/
intPush(SqStack&S,SElemTypee)
{
if(S.top-S.base>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+Stack_MoreNUM)*sizeof(SElemType));
if(!
S.base)exit(-1);
S.top=S.base+S.stacksize;
S.stacksize+=Stack_MoreNUM;
}
*S.top++=e;
returnOK;
}
/*拓扑排序*/
intTopoSort(ALGraphG,AdjListTemp,structNamename[])
{
inti,k,j=0,count,indegree[MAX_VERTEX_NUM];
SqStackS;
ArcNode*p;
FindInDegree(G,indegree);//对各顶点求入度
InitStack(S);//初始化栈
for(i=0;iif(!
indegree[i])Push(S,i);//入度为0者进栈
count=0;//对输出顶点计数
while(!
StackEmpty(S))
{
Pop(S,i);
printf("%s(%d分),",G.vertices[i].data,G.vertices[i].grades);
Temp[j++]=G.vertices[i];//将当前的拓扑序列保存起来
++count;//输出i号顶点并计数
for(p=G.vertices[i].firstarc;p;p=p->nextarc)//对i号顶点的每个邻接点的入度减1
{
k=p->adjvex;
if(!
(--indegree[k]))//若入度减为0,则入栈
Push(S,k);
}
}
if(count{
printf("此有向图有回路无法完成拓扑排序");
returnERROR;
}
elseprintf("为一个拓扑序列");
printf("\n");
intq=1,Z=0;
while(q<=TotalTerms)
{
intC=Temp[Z].grades;
printf("\n第%d个学期应学课程:
",q);
while(C<=MaxScores)
{
C=C+Temp[Z+1].grades;
if(Z{
printf("%4s",Temp[Z].data);
if(strcmp(Temp[Z].data,"c1")==0)
printf("程序设计基础");
if(strcmp(Temp[Z].data,"c2")==0)
printf("离散数学");
if(strcmp(Temp[Z].data,"c3")==0)
printf("数据结构");
if(strcmp(Temp[Z].data,"c4")==0)
printf("汇编语言");
if(strcmp(Temp[Z].data,"c5")==0)
printf("语言的设计和分析");
if(strcmp(Temp[Z].data,"c6")==0)
printf("计算机原理");
if(strcmp(Temp[Z].data,"c7")==0)
printf("编译原理");
if(strcmp(Temp[Z].data,"c8")==0)
printf("操作系统");
if(strcmp(Temp[Z].data,"c9")==0)
printf("高等数学");
if(strcmp(Temp[Z].data,"c10")==0)
printf("线性代数");
if(strcmp(Temp[Z].data,"c10")==0)
printf("普通物理");
if(strcmp(Temp[Z].data,"c12")==0)
printf("数值分析");
++Z;
}
}
printf("\n");
if(q==TotalTerms)printf("\n课程编制完成!
");
q++;
}
returnOK;
}
voidmain()
{
ALGraphG;
AdjListTemp;
structNamename[N]={{"C1"},{"C2"},{"C3"},{"C4"},{"C5"},{"C6"},{"C7"},{"C8"},{"C9"},{"C10"},{"C11"},{"C12"}};
OUTPUT();
printf("**********教学计划编制问题**********\n");
printf("请输入学期总数:
");
scanf("%d",&TotalTerms);
printf("请输入学期的学分上限:
");
scanf("%d",&MaxScores);
CreateGraph(G);
Display(G);
TopoSort(G,Temp,name);
printf("OK\n");
scanf("*c");
}
第五部分:
运行与测试
运行结果:
第六部分:
参考资料
《数据结构》(C语言版)作者:
严蔚敏、吴伟民 清华大学出版社
第七部分:
后记
课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。
随着科学技术发展的日新月异,计算机的应用空前活跃,计算机的语言问题也就显的尤为重要。
因此作为以为21世纪的大学生来说,掌握一门基础语言是非常重要的。
回顾此次数据结构课程设计,虽然在作业过程中遇到很多麻烦,但最终都圆满的解决了