课程设计报告模板.docx
《课程设计报告模板.docx》由会员分享,可在线阅读,更多相关《课程设计报告模板.docx(23页珍藏版)》请在冰豆网上搜索。
![课程设计报告模板.docx](https://file1.bdocx.com/fileroot1/2023-1/28/09fe157d-bfb6-496e-97b6-b3bd2236ee90/09fe157d-bfb6-496e-97b6-b3bd2236ee901.gif)
课程设计报告模板
《算法与数据结构》课程设计报告
题目:
教学计划编制问题
专业:
网络工程
班级:
2
学号:
1030040259
姓名:
魏益松
指导教师:
姜忠海
完成日期:
2012年6月24日
一、课程设计目的
本课程设计的目标就是要达到理论与实际应用相结合,提高学生组织数据及编写大型程序的能力,并培养基本的、良好的程序设计技能以及合作能力。
设计中要求综合运用所学知识,上机解决一些与实际应用结合紧密的、规模较大的问题,通过分析、设计、编码、调试等各环节的训练,使学生深刻理解、牢固掌握数据结构和算法设计技术,掌握分析、解决实际问题的能力。
通过这次设计,要求在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解。
同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。
二、课程设计内容
针对计算机系本科课程,依据其相互依赖关系制定课程安排计划,其相互依赖关系如下图所示,并要求各学期课程数目大致相同且搭配适当。
[基本要求]
(1)求解上图的拓扑排序结果。
(2)上述课程在4学期上完,要求每学期上课的门数大致一样。
三、课程设计过程
1.需求分析
根据课程间的依赖关系,制定课程安排计划。
按照用户的输入建立一个邻接表,输出拓扑排序结果。
按照用户输入的课程数,学期数,课程间的先后关系数目以及课程间两两间的先后关系,程序执行后会给出每学期应学的课程。
(1)输入的形式和输入值的范围:
输入间用空格隔开。
要求用户输入的课程数小于20,学期数小于或是等于20,课程名的长度小于等于20个字符。
(2)输出的形式:
输出本程序使用的课程及先后关系表,输出各个顶点的入读数和邻接点,输出一个拓扑排序结果;输出各个学期应学的课程代号。
(3)程序所能达到的功能:
按照用户的输入,输出拓扑排序结果。
按照用户的输入,给出每学期应学的课程。
2.概要设计
1.头文件
#include
#include
#include
#include
usingnamespacestd;
#defineMAX_VERTEX_NUM20//最大顶点个数
2.定义链式队列
typedefintElemType;
typedefstructQNode
{ElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{QueuePtrfront;
QueuePtrrear;
}LinkQueue;
3.初始化链式队列
voidInitQueue(LinkQueue*Q)
{Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(Q->front))exit(0);
Q->front->next=NULL;}
4.判断空队列
intQueueEmpty(LinkQueueQ)
{if(Q.front==Q.rear)
return1;
else
return0;}
5.入队列
voidEnQueue(LinkQueue*Q,ElemTypee)
{QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(0);
p->data=e;p->next=NULL;
Q->rear->next=p;
Q->rear=p;}
6.出队列
voidDeQueue(LinkQueue*Q,ElemType*e)
{QueuePtrp;
if(Q->front!
=Q->rear)
{p=Q->front->next;
*e=p->data;
Q->front->next=p->next;
if(Q->rear==p)Q->rear=Q->front;
free(p);}
}
7.图与邻接表
typedefcharVertexType[20];//顶点信息(名称)
/*图的类型定义(邻接表存储结构)*/
typedefstructArcNode//链表结点
{intvexpos;//该弧所指向的顶点在数组中的位置
structArcNode*next;//指向当前起点的下一条弧的指针
}ArcNode;
typedefstructVNode//头结点
{VertexTypename;//顶点信息(名称)
intindegree;//顶点入度
ArcNode*firstarc;//指向当前顶点的第一条弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct
{AdjListvexhead;//邻接表头结点数组
intvexnum,arcnum;//图的顶点数和弧数
}ALGraph
8.定位顶点的头节点
intLocateVex(ALGraphG,VertexTypev)
{inti;
for(i=0;iif(strcmp(v,G.vexhead[i].name)==0)break;
returni;}
9.建立邻接表
intCreateGraph(ALGraph*G)//成功建立返回1,不成功则返回0
{inti,j,k;VertexTypev1,v2;ArcNode*newarc;
printf("\n输入有向图顶点数和弧数vexnum,arcnum:
");//输入顶点数和弧数
scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);//输入并判断顶点数和弧数是否正确
if((*G).vexnum<0||(*G).arcnum<0||(*G).arcnum>(*G).vexnum*((*G).vexnum-1))
{printf("\n顶点数或弧数不正确,有向图建立失败!
\n");return0;}
printf("\n输入%d个顶点:
",(*G).vexnum);//输入顶点名称
for(i=0;i<(*G).vexnum;i++)
{scanf("%s",(*G).vexhead[i].name);}
printf("\n顶点列表:
\n共有%d个顶点:
",(*G).vexnum);//输出顶点名称
for(i=0;i<(*G).vexnum;i++)
printf("%s",(*G).vexhead[i].name);
for(i=0;i<(*G).vexnum;i++)//邻接表初始化
{(*G).vexhead[i].firstarc=NULL;
(*G).vexhead[i].indegree=0;}
printf("\n\n输入%d条边:
vivj\n",(*G).arcnum);//输入有向图的边
for(k=0;k<(*G).arcnum;k++)
{scanf("%s%s",v1,v2);//v1是弧的起点(先决条件),v2是弧的终点
i=LocateVex(*G,v1);j=LocateVex(*G,v2);//定位顶点并判断顶点是否存在
if(i>=(*G).vexnum)
{printf("顶点%s不存在,有向图建立失败!
\n",v1);return0;}
if(j>=(*G).vexnum)
{printf("顶点%s不存在,有向图建立失败!
\n",v2);return0;}
newarc=(ArcNode*)malloc(sizeof(ArcNode));//前插法建顶点链表
newarc->vexpos=j;
if((*G).vexhead[i].firstarc==NULL)
{newarc->next=NULL;
(*G).vexhead[i].firstarc=newarc;}
else
{newarc->next=(*G).vexhead[i].firstarc->next;
(*G).vexhead[i].firstarc->next=newarc;}
(*G).vexhead[j].indegree++;//对应顶点入度计数加1
}
printf("\n有向图建立成功!
\n");
return1;
}
10.按邻接表方式输出有向图
voidPrintGraph(ALGraphG)
{inti;ArcNode*p;
printf("\n输出有向图:
\n");
for(i=0;i{printf("\n顶点:
%s",G.vexhead[i].name);
printf("入度:
%3d\n",G.vexhead[i].indegree);
p=G.vexhead[i].firstarc;
printf("邻接点:
");
while(p!
=NULL)
{printf("%s",G.vexhead[p->vexpos].name);
p=p->next;}
printf("\n");
}
}
11.输出本程序使用的课程及先后关系表
intCreateGraph2(ALGraph*G)
{/*输出本程序使用的课程及先后关系表*/
cout<<"课程及先修课程关系表"<cout<<"┌────┬───────┬────────┐"<cout<<"│课程代号│课程名称│先修课程│"<cout<<"├────┼───────┼────────┤"<cout<<"│c1│高等数学│无│"<cout<<"├────┼───────┼────────┤"<cout<<"│c2│程序设计│无│"<cout<<"├────┼───────┼────────┤"<cout<<"│c3│离散数学│c1│"<cout<<"├────┼───────┼────────┤"<cout<<"│c4│数据结构│c2c3│"<cout<<"├────┼───────┼────────┤"<cout<<"│c5│编译原理│c2c4│"<cout<<"├────┼───────┼────────┤"<cout<<"│c6│操作原理│c4c7│"<cout<<"├────┼───────┼────────┤"<cout<<"│c7│计算机组成原理│c2│"<cout<<"└────┴───────┴────────┘"<system("PAUSE");
(*G).vexnum=8;(*G).arcnum=16;
return0;
}
12.按邻接表方式输出课程图
voidPrintGraph2(ALGraphG)
{inti;ArcNode*p;
printf("\n输出有向图:
\n");
for(i=0;i{printf("\n课程:
%s",G.vexhead[i].name);
printf("入度:
%3d\n",G.vexhead[i].indegree);
p=G.vexhead[i].firstarc;
printf("以本课程为基础的课程:
");
while(p!
=NULL)
{printf("%s",G.vexhead[p->vexpos].name);
p=p->next;
}
printf("\n");
}
}
13.拓扑排序
voidTopologicalSort(ALGraphG)
{inti,k,count;ElemTypee;ArcNode*p;
LinkQueueQ;/*定义队列*/
InitQueue(&Q);
for(i=0;iif(!
G.vexhead[i].indegree)EnQueue(&Q,i);
count=0;//对输出课程计数变量初始化
printf("\n\n\n以上课程的一个拓扑排序序列为:
\n");
while(!
QueueEmpty(Q))
{DeQueue(&Q,&e);//先将入度为零的课程输出
printf("%s",G.vexhead[e].name);
count++;//对输出的顶点计数
for(p=G.vexhead[e].firstarc;p;p=p->next)//遍历当前课程的邻接点
{k=p->vexpos;//邻接点位置
if(!
(--G.vexhead[k].indegree))//每个邻接点入度减1后若为零则入队列
EnQueue(&Q,k);
}
}
printf("\n");
if(count{printf("\n该有向图有回路,无法完成拓扑排序!
\n");}
}
14.主函数
voidmain()
{ALGraphG;intmenu,menu2;
while
(1){
printf("\n**********************************************\n");
printf("*1.输出课程及先修课程关系表*\n");
printf("*2.建立有向图并求一个拓扑排序序列*\n");
printf("*3.退出*\n");
printf("**********************************************\n");
printf("请输入你的选择:
");
scanf("%d",&menu);
switch(menu){
case1:
if(CreateGraph2(&G)){//有向图建成则执操作
system("PAUSE");
PrintGraph2(G);system("PAUSE");
}
break;
case2:
if(CreateGraph(&G))//有向图建成则执操作
{system("PAUSE");
PrintGraph(G);system("PAUSE");
TopologicalSort(G);}
break;
case3:
return;
}
}
}
3.详细设计
1.教学计划编程问题,主要是根据不同课程之间的依赖关系来分配先后顺序。
是拓扑排序的应用,邻接表为主要存储结构,队列为辅助结构。
利用宏定义来完成一些变量的赋值:
2、本程序包含8个函数:
(1)主函数main()
(2)创建一个队列InitQueue()
(3)判断空队列QueueEmpty()
(4)入队操作enqueue()
(5)出队操作dequeue()
(6)定位顶点LocateVex()
(7)创建邻接表CreateGraph()
(8)输出有向图PrintGraph()
(9)拓扑排序TopologicalSort()
(10)菜单操作menu()
4.调试分析
调试过程中遇到很多问题,大多是和同学讨论共同修改。
由于只输出拓扑排序结果,没有输出学期安排,用队列存储不知道怎么实现学期安排,又编写了一个用栈来存储的学期输出程序,在附录中有。
5.用户使用说明
根据提示输入。
6.测试结果
7.附录
#include
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
typedefintStatus;
typedefintBoolean;
#defineMAX_NAME10
#defineMAXCLASS100
intZ=0;
intX=0;
intxqzs,q=1,xfsx;
typedefintInfoType;
typedefcharVertexType[MAX_NAME];/*字符串类型*/
/*图的邻接表存储表示*/
#defineMAX_VERTEX_NUM100
typedefenum{DG}GraphKind;
typedefstructArcNode
{
intadjvex;
structArcNode*nextarc;
InfoType*info;
}ArcNode;
typedefstruct
{
VertexTypedata;/*顶点信息*/
ArcNode*firstarc;/*第一个表结点的地址,指向第一条依附该顶点的弧的指针*/
}VNode,AdjList[MAX_VERTEX_NUM];/*头结点*/
typedefstruct
{
AdjListvertices,verticestwo;
intvexnum,arcnum;/*图的当前顶点数和弧数*/
intkind;/*图的种类标志*/
}ALGraph;
/*图的邻接表存储的基本操作*/
intLocateVex(ALGraphG,VertexTypeu)
{/*初始条件:
图G存在,u和G中顶点有相同特征*/
/*操作结果:
若G中存在顶点u,则返回该顶点在图中位置;否则返回-1*/
inti;
for(i=0;iif(strcmp(u,G.vertices[i].data)==0)
returni;
return-1;
}
StatusCreateGraph(ALGraph*G)
{/*采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造种图)*/
inti,j,k;
VertexTypeva,vb;
ArcNode*p;
(*G).vexnum=7;
printf("请输入拓扑排序所形成的课程先修关系的边数:
");
scanf("%d",&(*G).arcnum);
printf("请输入7个课程的代表值(7个字符):
\n",(*G).vexnum,MAX_NAME);
for(i=0;i<(*G).vexnum;++i)/*构造顶点向量*/
{scanf("%s",(*G).vertices[i].data);
(*G).vertices[i].firstarc=NULL;
}
printf("请输入每条弧(边)的弧头和弧尾(以空格作为间隔):
\n");
for(k=0;k<(*G).arcnum;++k)/*构造表结点链表*/
{scanf("%s%s",va,vb);
i=LocateVex(*G,va);/*弧头*/
j=LocateVex(*G,vb);/*弧尾*/
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info=NULL;/*图*/
p->nextarc=(*G).vertices[i].firstarc;/*插在表头*/
(*G).vertices[i].firstarc=p;
}
returnOK;
}
voidDisplay(ALGraphG)
{/*输出图的邻接矩阵G*/
inti;
ArcNode*p;
switch(G.kind)
{caseDG:
printf("有向图\n");
}
printf("%d个顶点:
\n",G.vexnum);
for(i=0;iprintf("%s",G.vertices[i].data);
printf("\n%d条弧(边):
\n",G.arcnum);
for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{printf("%s→%s",G.vertices[i].data,G.vertices[p->adjvex].data);
p=p->nextarc;
}
printf("\n");
}
}
voidFindInDegree(ALGraphG,intindegree[])
{/*求顶点的入度,算法调用*/
inti;
ArcNode*p;
for(i=0;iindegree[i]=0;/*赋初值*/
for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{indegree[p->adjvex]++;
p=p->nextarc;
}
}
}
typedefintSElemType;/*栈类型*/
/*栈的顺序存储表示*/
#defineSTACK_INIT_SIZE10/*存储空间初始分配量*/
#defineSTACKINCREMENT2/*存储空间分配增量*/
typedefstructSqStack
{
SElemType*base;/*在栈构造之前和销毁之后,base的值为NULL*/
SElemType*top;/*栈顶指针*/
intstacksize;/*当前已分配的存储空间,以元素为单位*/
}SqStack;/*顺序栈*/
/*顺序栈的基本操作*/
StatusInitStack(SqSta