1、数据结构课程设计之课程表实现软 件 学 院课程设计报告书课程名称 数据结构 设计题目 教学计划编制 专业班级 软件10-04班 学 号 * 姓 名 张小龙 指导教师 刘玲玲 2012年 1 月1 设计时间 2012年1月3日至2012年1月5日2 设计目的 (1)加强学生分析问题能力和应用所学知识解决问题的能力;(2)使学生对所学内容更深入的了解和应用;(3)提高C程序调试能力,加强程序设计和实践能力;(4)加深学生对数据结构和C语言等相关课程的认识;(5)培养学生自主软件设计能力和开发能力;(6)加强个人程序设计能力和学生与学生之间的交流和研讨。3设计任务大学的每个专业都要制定教学计划。假设
2、任何专业都有固定的学习年限,每学年含两学期,每学期的时间长度和学分上限值均相等。每个专业开设的课程都是确定的,而且课程在开设时间的安排必须满足先修关系。每门课程有哪些先修课程是确定的,可以有任意多门,也可以没有。每门课恰好占一个学期。试在这样的前提下设计一个教学计划编制程序。任选软件专业几门课程作为顶点,通过这几门课程的先修关系来构建一个有向图,用邻接表来储存,通过栈和有向图来完成课程教学计划安排。4 设计内容4.1需求分析 1、程序所能达到的功能(1)数据结构使用有向图和栈。 (2)课程先修关系(表4.1-01)(表4.1-01课程先修关系) (3)如果输入的先修课程号不在该专业开设的课程序
3、列内,则作为错误处理。2、输入的形式和输入值的范围输入参数包括:学期总数,一学期的学分上限,每门课的课程号(固定占3位的字母数字串)、学分和直接先修课的课程号。3、输出的形式每学期课程安排4、测试数据: 学期总数6,一学期的学分上限16,该专业共开课程数目14,按照表4.1-01输入课程名,课程号,课程学分。输出正确的课程编排结果。4.2总体设计1、说明本程序中用到的所有抽象数据类型的定义ADT Graph数据对象V:V是具有相同特性的数据元素的集合,称为顶点集.数据关系R:R=VRVR=(v,w)|v,wV,(v,w)表示v和w之间存在直接先修关系基本操作P:void CreatGraph(
4、ALGraph *G)操作结果:创造图Gvoid InitStack(SqSttack *S)操作结果:构造一个空栈Svoid StackEmpty(SqStack *S)初始条件:栈S已存在操作结果:若栈S为空栈,则返回TRUE,否则FALSEvoid Push(SqStack *S,int e)初始条件:栈S已存在操作结果:插入元素e为新的栈顶元素void Pop(SqStack *S,int *e)初始条件:栈S已存在且非空操作结果:删除S的栈顶元素,并用e返回其值void FindInDegree(ALGraph G, int indegree)初始条件:拓扑排序完成操作结果:构造关键
5、路径的先修关系网void TopologicalSort_1(ALGraph G,int numterm,int uplcredit)初始条件:图G已存在操作结构:进行拓扑排序,并完成关系网的构造,使课程尽可能集中在前几个学期void TopologicalSort_2(ALGraph G,int numterm,int uplcredit)初始条件:图G已存在操作结果:进行拓扑排序,并完成关系网的构造,使课程尽量均匀分布ADT Graph2、说明主程序的流程3、说明各程序模块之间的层次(调用)关系(图4.2-3)4.3详细设计1、实现概要设计中定义的所有数据类型,对每个操作只需要写出伪码算法
6、1)采用邻接表存储结构,构造没有相关信息的图G,并储存键入的相关信息 void CreatGraph(ALGraph *G) 通过循环语句完成对键入的课程名称,课程号,学分的存储,并课程先修关系建立邻接表 for (i = 1; i arcnum; i+) /* 构造顶点向量 */ printf(n请输入存在先修关系的两个课程的序号:); scanf(&n,&m); while (课程号不在编入范围) printf(输入的顶点序号不正确 请重新输入:); scanf(&n,&m); 分配头结点的存储空间 if (p为空) printf(分配失败); 建立邻接表 printf(建立的邻接表);f
7、or(i=1;ivexnum;i+) printf(%d:-,G-verticesi.classid); for(p=G-verticesi.firstarc;p!=NULL;p=p-nextarc) printf(%d-,p-adjvex); printf(NULL); printf(n); 2)构造一个空栈Svoid InitStack(SqStack *S) 赋予顺序栈足够的存储空间 if (!S-base) printf(存储分配失败) exit(1); top=base初始栈为空,存储空间为所分配的足够的存储空间3)判断是否为空栈int StackEmpty(SqStack *S)
8、if(栈S为空栈) return OK; else return ERROR;4)入栈操作void Push(SqStack *S,int e) 插入元素e为新的栈顶元素 if(栈满)为栈重新分配存储空间 if(!S-base) printf(存储分配失败) exit(1); top=base初始栈为空,存储空间为所分配的足够的存储空间 栈顶指针上移5. 取栈顶操作int Pop(SqStack *S, int *e) 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR if(栈顶元素为空) exit(1); 栈顶指针下移并将其值返回给*e6)求图中各节点的入度void
9、 FindInDegree(ALGraph G, int indegree) for (i = 1; i = G.vexnum; i+) indegreei = 0; for (i = 1; i adjvex+; G.verticesi.firstarc = G.verticesi.firstarc-nextarc; 7)有向图G采用邻接表存储结构void TopologicalSort_1(ALGraph G,int numterm,int uplcredit)若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR。 int indegreeM;存放各节点的入度 int co
10、unt; 课程编排数目计数器 int sumcredit;每个学期的课程学分累加器 FindInDegree(G, indegree);对各顶点求入度indegree0.vernum-1 for (i = 1; i = G.vexnum; i+) G.verticesi.indegree=indegreei; 初始化栈 while(count!=G.vexnum & k=numterm) sumcredit=0; for(无先修的课程入栈) if(G.verticesi.indegree=0)&(G.verticesi.state=NOTSTUDY) Push(&S,i); G.vertice
11、si.state = STUDY;避免入度为零节点重复入栈 if(栈非空且学分计数器小于学分上限) k= k+1; printf(第%d个学期学得课程有:n,k); for(i=1;i=G.vexnum;i+)入度为零的节点入栈,即无先修的课程入栈 if(G.verticesi.indegree=0)&(G.verticesi.state=NOTSTUDY) Push(&S,i); while(栈非空&学分总数小于学分上限) Pop(&S,&j); sumcredit = sumcredit + G.verticesj.credit; if(学分计数器小于等于学分上限) printf( %s
12、,G.verticesj.name); 课程数目累加 对j号顶点每个邻接点的入度减一 将未输出的节点重新压入栈 if(被编排课程编排课程总数) printf(课程编排出错); else printf(课程编排成功); 8) 有向图G采用邻接表存储结构若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERRORvoid TopologicalSort_2(ALGraph G,int numterm,int uplcredit) 头结点指针P调用栈S FindInDegree(G, indegree); for (i = 1; i = G.vexnum; i+) G.verticesi.
13、indegree = indegreei; InitStack(&S); 课程编排计数器赋值为0 课程名计数器赋值 maxnum = G.vexnum/numterm+1; sumnum = 0; while(count!=G.vexnum & k=numterm) for(i=1;i=G.vexnum;i+) 入度为零的节点入栈,即无先修的if(G.verticesi.indegree=0)&(G.verticesi.state=NOTSTUDY) Push(&S,i); G.verticesi.state = STUDY; if(栈非空,学分计数器小于学分上限) k= k+1; print
14、f(第%d个学期学得课程有:,k); sumcredit = 0; sumnum = 0; for(i=1;i=G.vexnum;i+)入度为零的节点入栈,即无先修的课程入栈 if(G.verticesi.indegree=0)&(G.verticesi.state=NOTSTUDY)Push(&S,i); while(栈非空&学分总数小于学分上限&学期课程数目小于学期最大数目) 出栈 积分器累加 sumnum = sumnum+1; if(sumcredit = uplcredit)&(sumnum adjvex.indegree-; else Push(&S,j); if(课程未全部编排,
15、有剩余) printf(课程编排出错) else printf(课程编排成功) 2、对主程序和其它主要函数写出伪码算法int main() int numterm; /*学期总数*/ int uplcredit; /*一个学期的学分上限*/ int selectway; 建立邻接表 scanf(%d,&numterm); 输入学期总数 scanf(%d,&uplcredit); 输入一个学期的学分上限 printf(选择编排策略:1.课程尽可能集中到前几个学期;2.课程尽量均匀分布); if(选择1) TopologicalSort_1(G,numterm,uplcredit); if(选择2
16、) TopologicalSort_2(G,numterm,uplcredit); return 0;3、画出函数的调用关系图(图4.3-03)4.4测试与分析4.4.1测试学期总数: 6 一学期的学分上限: 16 该专业共开课程数目: 141.键入学期总数,学分上限,安排课程总数2.输入课程名,课程号及相应学分3.输入课程先修关系总数 4.顺序输入先修关系 5.输出邻接表6.选择编排策略1,输出编排结果7. 选择编排策略2,输出编排结果8.错误运行:当输入两个相同课程号的不同课程,当输入先修顺序有环时9.运行结果:4.4.2分析1、调试过程中遇到的问题是如何解决的以及对设计与实现的回顾讨论和
17、分析 调试过程中出现了很多问题,例如定义了无关变量、程序逻辑性错误等。在种种错误下,自己根据提示修改了一部分简单错误。对于其他错误,常常误认为是正确的,而不得改正。无奈下求助同学帮助,在几个同课题同学帮助下,纠正了大多数问题。其他几个复杂问题上网查阅资料,询问老师才最终解决。设计两个不同拓扑的程序是遇到很多大麻烦,平时实验不涉及该内容,书上仅仅提供了一个算法。在上网查阅资料,求助同学下才完成了框架。面对程序考略不足,漏缺重要条件和关键步骤,遇到到了很大麻烦。究其原因还是基础不牢,缺乏实验,动手能力差。2、算法的时间复杂度和空间复杂度的分析本程序算法的时间复杂度为O(n),空间复杂度为O(2n)
18、 4.5 附录源程序代码及必要注释/* Note:Your choice is C IDE */#include stdio.h#include string.h#include malloc.h#include stdlib.h/* *图的邻接表存储表示* */#define MAX_VERTEX_NUM 100 /最大课程总数#define STACK_INIT_SIZE 100 /存储空间的初时分配量#define STACKINCREMENT 10 /存储空间的分配增量#define OK 1#define ERROR 0#define M 100#define NOTSTUDY -1
19、#define STUDY 1typedef struct ArcNode int adjvex; /该弧所指向的顶点的位置 struct ArcNode *nextarc; /指向下一条弧的指针ArcNode;typedef struct VNode char name30; /课程名 int classid; /课程号 int credit; /课程的学分 int indegree; /该结点的入度 int state; /该节点的状态 ArcNode *firstarc; /第一个表结点的地址,指向第一条依附该顶点的弧的指针 VNode,AdjList100;typedef int El
20、emType;typedef struct AdjList vertices; int vexnum, arcnum; /图的当前顶点数和弧数 ALGraph;typedef struct ElemType *base; /在栈构造之前和销毁之后,base的值为NULL ElemType *top; /栈顶指针 int stacksize; /当前已分配的存储空间,以元素为单位 SqStack; /顺序栈 /* *图的构建* */void CreatGraph(ALGraph *G) /采用邻接表存储结构,构造没有相关信息的图G,并储存键入的相关信息 int i, m, n,f100=0; A
21、rcNode *p; printf(请输入需要编排课程总数:n); scanf(%d,&G-vexnum); for(i=1;ivexnum;i+) /构造顶点向量 printf(请输入课程名n); scanf(%s,&G-verticesi.name); A:printf(请输入课程号n); scanf(%d,&G-verticesi.classid); if(fG-verticesi.classid)printf(课程号重复,请重新输入n); goto A; else fG-verticesi.classid=1; printf(请输入该课程的学分n); scanf(%d,&G-verti
22、cesi.credit); G-verticesi.indegree=G-vertices i.state=NOTSTUDY; G-verticesi.firstarc=NULL; printf(请输入课程先修关系总数:); scanf(%d,&G-arcnum); printf(请顺序输入每个课程先修关系(先修课程在前并以逗号作为间隔):n); for (i = 1; i arcnum; i+) /构造顶点向量 printf(n请输入存在先修关系的两个课程的序号:); scanf(%d,%d,&n,&m); while (n G-vexnum | m G-vexnum) printf(输入的
23、顶点序号不正确 请重新输入:); scanf(%d,%d,&n,&m); p = (ArcNode*)malloc(sizeof(ArcNode); if (p = NULL) printf(memory allocation failed,goodbey); exit(1); p-adjvex = m; p-nextarc = G-verticesn.firstarc; G-verticesn.firstarc = p; printf(n建立的邻接表为:n); /输出建立好的邻接表 for(i=1;ivexnum;i+) printf(%d:-,G-verticesi.classid); f
24、or(p=G-verticesi.firstarc;p!=NULL;p=p-nextarc) printf(%d-,p-adjvex); printf(NULL); printf(n); /* *顺序栈的基本操作* */ void InitStack(SqStack *S) /构造一个空栈S S-base=(int *)malloc(STACK_INIT_SIZE *sizeof(int); if (!S-base) printf(ERROR); /存储分配失败 exit(1); S-top=S-base; S-stacksize=STACK_INIT_SIZE;int StackEmpty(
25、SqStack *S) /若栈S为空栈,则返回TRUE,否则 返回FALSE if(S-top=S-base) return OK; else return ERROR;/* *入栈* */void Push(SqStack *S,int e) / 插入元素e为新的栈顶元素 if(S-top - S-base = S-stacksize) S-base = (int *) realloc (S-base , (S-stacksize + STACKINCREMENT) * sizeof(int); if(!S-base) printf(ERROR); /存储分配失败 exit(1); S-to
26、p = S-base + S-stacksize; S-stacksize += STACKINCREMENT; *S-top+ = e;/* *出栈* */int Pop(SqStack *S, int *e) / 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR if(S-top = S-base) exit(1); *e = * -S-top; return 0;/* *寻找各节点入度* */void FindInDegree(ALGraph G, int indegree) /求图中各节点的入度 int i; for (i = 1; i = G.vexnum;
27、 i+) indegreei = 0; for (i = 1; i adjvex+; G.verticesi.firstarc = G.verticesi.firstarc-nextarc; /* *课程尽量集中到前几学期的拓扑排序* */void TopologicalSort_1(ALGraph G,int numterm,int uplcredit)/* 有向图G采用邻接表存储结构。若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR。*/ int i=0,j, k; ArcNode *p; SqStack S; int indegreeM; /存放各节点的入度 int
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1