拓扑排序课程设计论文Word格式.docx
- 文档编号:19719538
- 上传时间:2023-01-09
- 格式:DOCX
- 页数:26
- 大小:325.14KB
拓扑排序课程设计论文Word格式.docx
《拓扑排序课程设计论文Word格式.docx》由会员分享,可在线阅读,更多相关《拓扑排序课程设计论文Word格式.docx(26页珍藏版)》请在冰豆网上搜索。
1.本表应在每次实施前一周由负责教师填写二份,教研室审批后交学院院备案,一份由负责教师留用。
2.若填写内容较多可另纸附后。
3.一题多名学生共用的,在设计内容、参数、要求等方面应有所区别。
教研室主任:
指导教师:
2015年1月9日
目录
1问题描述1
2基本要求1
3算法思想1
4数据结构2
4.1链式队列的存储类型为2
4.2图的类型(邻接表存储结构)为2
5模块划分2
5.1链式队列操作2
5.2有向图(DAG)邻接表存储结构(ALG)的操作3
5.3拓扑排序及拓扑检测算法3
5.4主函数4
6测试数据4
6.1对“建立有向图并输出”的测试4
6.2对“建立有向图并求一个拓扑排序序列”的测试4
6.3对“检测用户输入的课程安排”的测试4
7测试情况5
7.1对“建立有向图并输出”的测试5
7.2对“建立有向图并求一个拓扑排序序列”的测试7
7.3对“检测用户输入的课程安排”的测试8
8系统开发所用到的技术11
参考文献13
附录全部代码14
1问题描述
在AOV网中为了更好地完成工程,必须满足活动之间先后关系,需要将各活动排一个先后次序即为拓扑排序。
拓扑排序可以应用于教学计划的安排,根据课程之间的依赖关系,制定课程安排计划。
按照用户输入的课程数,课程间的先后关系数目以及课程间两两间的先后关系,程序执行后会给出符合拓扑排序的课程安排计划。
2基本要求
1、选择合适的存储结构,建立有向无环图,并输出该图;
2、实现拓扑排序算法;
3、运用拓扑排序实现对教学计划安排的检验。
3算法思想
1、采用邻接表存储结构实现有向图;
有向图需通过顶点数、弧数、顶点以及弧等信息建立。
2、拓扑排序算法voidTopologicalSort(ALGraphG)中,先输出入度为零的顶点,而后输出新的入度为零的顶点,此操作可利用栈或队列实现。
考虑到教学计划安排的实际情况,一般先学基础课(入度为零),再学专业课(入度不为零),与队列先进先出的特点相符,故采用队列实现。
3、拓扑排序算法voidTopologicalSort(ALGraphG),大体思想为:
1)遍历有向图各顶点的入度,将所有入度为零的顶点入队列;
2)队列非空时,输出一个顶点,并对输出的顶点数计数;
3)该顶点的所有邻接点入度减一,若减一后入度为零则入队列;
4)重复2)、3),直到队列为空,若输出的顶点数与图的顶点数相等则该图可拓扑排序,否则图中有环。
4、要对教学计划安排进行检验,因此编写了检测用户输入的课程序列是否是拓扑序列的算法voidTopSortCheck(ALGraphG),大体思想为:
1)用户输入待检测的课程序列,将其存入数组;
2)检查课程序列下一个元素是否是图中的顶点(课程),是则执行3),否则输出“课程XX不存在”并跳出;
3)判断该顶点的入度是否为零,是则执行4),否则输出“入度不为零”并跳出;
4)该顶点的所有邻接点入度减一;
5)重复2)、3)、4)直到课程序列中所有元素均被遍历,则该序列是拓扑序列,否则不是拓扑序列。
4数据结构
4.1链式队列的存储类型为
typedefintElemType;
typedefstructQNode
{ElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{QueuePtrfront;
QueuePtrrear;
}LinkQueue;
4.2图的类型(邻接表存储结构)为
typedefcharVertexType[20];
//顶点信息(名称)
typedefstructArcNode//链表结点
{intvexpos;
//该弧所指向的顶点在数组中的位置
structArcNode*next;
//指向当前起点的下一条弧的指针
}ArcNode;
typedefstructVNode//头结点
{VertexTypename;
intindegree;
//顶点入度
ArcNode*firstarc;
//指向当前顶点的第一条弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
{AdjListvexhead;
//邻接表头结点数组
intvexnum,arcnum;
//图的顶点数和弧数
}ALGraph;
5模块划分
5.1链式队列操作
1)voidInitQueue(LinkQueue*Q)
功能:
初始化链式队列
参数:
*Q待初始化的队列
2)intQueueEmpty(LinkQueueQ)
判断空队列
Q待判断的队列
返回值:
队列为空返回1;
队列非空返回0
3)voidEnQueue(LinkQueue*Q,ElemTypee)
元素入队列
*Q待操作的队列;
e要入队列的元素
4)voidDeQueue(LinkQueue*Q,ElemType*e)
元素出队列
*e记录出队列元素的变量
5.2有向图(DAG)邻接表存储结构(ALG)的操作
1)intLocateVex(ALGraphG,VertexTypev)
顶点在头结点数组中的定位
G待操作的图;
v要在图中定位的顶点
顶点存在则返回在头结点数组中的下标;
否则返回图的顶点数
2)intCreateGraph(ALGraph*G)
建立图
函数内包含了由用户输入顶点数、弧数、顶点以及弧的操作
*G待操作的图
图建立成功返回1;
图建立失败返回0
错误判断:
包含顶点数、弧数是否正确的判断;
包含用户输入的弧的顶点是否存在的判断
3)voidPrintGraph(ALGraphG)
输出有向图
G待输出的图
4)intCreateGraph2(ALGraph*G)
建立预置课程图(输出函数内预置课程信息,并自动建立有向图)
包含顶点数、弧数是否正确的判断
包含弧的顶点是否存在的判断
5)voidPrintGraph2(ALGraphG)
输出预置课程图
5.3拓扑排序及拓扑检测算法
1)voidTopologicalSort(ALGraphG)
实现拓扑排序
G待进行拓扑排序的图
包含有向图是否有环的判断
2)voidTopSortCheck(ALGraphG)
运用拓扑排序的思想检测教学计划
函数内包含了由用户输入待检测的课程序列的操作
G待操作的图
包含用户输入的课程是否存在的判断
包含不是拓扑序列的原因(该课程有多少个先决课程未学)
5.4主函数
voidmain()
主函数
利用while语句和switch语句实现菜单化调用函数
6测试数据
6.1对“建立有向图并输出”的测试
1)正确的有向图信息
顶点数和弧数:
4,3
顶点:
ABCD
边:
ABBCCD
2)错误的边
ABBCCE
3)错误的顶点数或弧数
3,7
6.2对“建立有向图并求一个拓扑排序序列”的测试
1)有向图能实现拓扑排序
5,5
ABCDE
ADDCCBEAEC
2)有向图不能实现拓扑排序
ADDCCBEABA
6.3对“检测用户输入的课程安排”的测试
1)课程序列符合拓扑序列
课程序列:
C9C10C11C6C1C12C4C2C3C5C7C8
2)课程序列中有课程不存在
课程序列:
C9C10C11C6C1C12C4C2C13C5C7C8
3)课程序列不是拓扑序列
C9C10C11C1C8C6C12C4C2C3C5C7
7测试情况
程序初始执行界面(以下测试编号与本文第七节测试数据编号一一对应)
7.1对“建立有向图并输出”的测试
1)正确的有向图信息
有向图信息正确的情况下,程序显示“有向图建立成功”,并输出有向图。
本测试中,第三条边(CE)的一个顶点E不是有向图中的顶点,程序能判断本错误并显示相应的提示信息。
本测试中,顶点数和弧数分别为3,7。
若有向图共有n个顶点,两顶点间最多有2条有向边,则有向图最多有n*(n-1)条边。
而3*(3-1)=6<
7,故程序提示“顶点数或弧数不正确,有向图建立失败”;
程序还能判断负的顶点数和弧数。
7.2对“建立有向图并求一个拓扑排序序列”的测试
有向图能实现拓扑排序的情况下,程序输出其中一个拓扑排序序列。
本测试中,有向图其中四条边(AD)、(DC)、(CB)、(BA)构成环,程序能判断有向图有回路并提示相应信息。
7.3对“检测用户输入的课程安排”的测试
程序首先输出预置的课程信息和据此建立的有向图。
1)课程序列符合拓扑序列
在用户输入的课程序列符合拓扑序列的情况下,程序提示“本课程序列符合拓扑序列”,并显示如图菜单。
本程序预置了C1-C12共12门课程,若用户输入的课程序列中有不属于预置课程的课程,程序会提示“课程XX不存在!
”,并显示如图菜单。
若用户输入的课程序列不是拓扑序列,程序会输出原因,即“学习课程XX时,还有X门先决课程未学!
”,并显示如图菜单。
8系统开发所用到的技术
操作系统:
WindowsXP
开发软件:
VisualC++6.0
技术:
功能模块(函数);
指针;
结构;
链表;
文件保存及读取。
模块与函数:
功能模块:
求解较小问题的算法与程序称作“功能模块”,各功能模块可以先单独设计,然后将求解所有的子问题的模块组合成求解原问题的程序。
将一个大问题分解成多个解决小问题的模块的设计思想。
由功能模块组成程序的结构:
主控模块和模块组成。
模块还可细分。
自顶向下,逐步分解的设计思想
函数:
完成相对独立功能和程序。
模块独立:
功能独立的子功能模块之间的关系简单,使用独立变量,模块规模适当:
分解模块要注意层次:
(1)对问题抽象化
(2)设计时细化
设计原则:
高内聚,低耦合
指针就是指向变量和对象的地址。
指针的用途非常广泛,比如如果你想通过函数改变一个变量的值,就得用指针而不能用值传递。
还有在很多时候变量,特别是对象的数据量实在太大,程序员就会用指针来做形参,只需要传递一个地址就行,大大提高了效率。
指针的用途非常广泛,比如如果你想通过函数改变一个变量的值,就得用指针而不能用值传递。
c语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。
因此,说指针是c语言的灵魂,一点都不为过。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:
一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比于线性表顺序结构,链表比较方便插入和删除操作。
参考文献
中国水利水电出版社,2014.7
中国水利水电出版社,2014.9
附录全部代码
#include"
stdlib.h"
stdio.h"
string.h"
/*******************************************/
/*以下为链式队列操作*/
/*定义链式队列类型*/
structQNode*next;
QueuePtrrear;
/*1.初始化链式队列*/
voidInitQueue(LinkQueue*Q)
{Q->
front=Q->
rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(Q->
front))exit(0);
Q->
front->
next=NULL;
}
/*2.判断空队列*/
intQueueEmpty(LinkQueueQ)
{if(Q.front==Q.rear)
return1;
else
return0;
/*3.入队列*/
voidEnQueue(LinkQueue*Q,ElemTypee)
{QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
p)exit(0);
p->
data=e;
rear->
next=p;
rear=p;
/*4.出队列*/
voidDeQueue(LinkQueue*Q,ElemType*e)
if(Q->
front!
=Q->
rear)
{p=Q->
next;
*e=p->
data;
Q->
next=p->
if(Q->
rear==p)Q->
rear=Q->
front;
free(p);
}
/****************************************************/
/*以下为有向图(DAG)邻接表存储结构(ALG)的操作*/
#defineMAX_VERTEX_NUM20//最大顶点个数
//顶点信息(名称)
/*图的类型定义(邻接表存储结构)*/
typedefstructArcNode//链表结点
//该弧所指向的顶点在数组中的位置
//指向当前起点的下一条弧的指针
typedefstructVNode//头结点
//顶点入度
//指向当前顶点的第一条弧的指针
//邻接表头结点数组
//图的顶点数和弧数
/*5.顶点在头结点数组中的定位*/
intLocateVex(ALGraphG,VertexTypev)
{inti;
for(i=0;
i<
G.vexnum;
i++)
if(strcmp(v,G.vexhead[i].name)==0)break;
returni;
/*6.建立图(邻接表)*/
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;
\n输入%d个顶点:
(*G).vexnum);
//输入顶点名称
(*G).vexnum;
{scanf("
%s"
(*G).vexhead[i].name);
\n顶点列表:
\n共有%d个顶点:
"
//输出顶点名称
printf("
%s"
i++)//邻接表初始化
{(*G).vexhead[i].firstarc=NULL;
(*G).vexhead[i].indegree=0;
\n\n输入%d条边:
vivj\n"
(*G).arcnum);
//输入有向图的边
for(k=0;
k<
(*G).arcnum;
k++)
%s%s"
v1,v2);
//v1是弧的起点(先决条件),v2是弧的终点
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
//定位顶点并判断顶点是否存在
if(i>
=(*G).vexnum)
{printf("
顶点%s不存在,有向图建立失败!
v1);
}if(j>
v2);
newarc=(ArcNode*)malloc(sizeof(ArcNode));
//前插法建顶点链表
newarc->
vexpos=j;
if((*G).vexhead[i].firstarc==NULL)
{newarc->
(*G).vexhead[i].firstarc=newarc;
else
next=(*G).vexhead[i].firstarc->
(*G).vexhead[i].firstarc->
next=newarc;
(*G).vexhead[j].indegree++;
//对应顶点入度计数加1
}
\n有向图建立成功!
return1;
/*7.按邻接表方式输出有向图*/
voidPrintGraph(ALGraphG)
ArcNode*p;
\n输出有向图:
i<
i++)
\n顶点:
G.vexhead[i].name);
printf("
入度:
%3d\n"
G.vexhead[i].indegree);
p=G.vexhead[i].firstarc;
邻接点:
while(p!
=NULL)
G.vexhead[p->
vexpos].name);
p=p->
//为避免演示时要输入过多数据,以下函数将课程编号、课程间的先后关系通过数组预置
/*8.建立预置课程图(邻接表)*/
intCreateGraph2(ALGraph*G)//成功建立返回1,不成功则返回0
ArcNode*newarc;
VertexTypeSubjectName[12]={"
C1"
"
C2"
C3"
C4"
//课程名称
C5"
C6"
C7"
C8"
C9"
C10"
C11"
C12"
},
RelationV1[16]={"
//基础课
},
RelationV2[16]={"
//以上面课程为基础的课
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 拓扑 排序 课程设计 论文
![提示](https://static.bdocx.com/images/bang_tan.gif)