您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > 拓扑排序(算法与数据结构课程设计)
wilyes11收集博客(与学习无关):拓扑排序一、问题描述在AOV网中为了更好地完成工程,必须满足活动之间先后关系,需要将各活动排一个先后次序即为拓扑排序。拓扑排序可以应用于教学计划的安排,根据课程之间的依赖关系,制定课程安排计划。按照用户输入的课程数,课程间的先后关系数目以及课程间两两间的先后关系,程序执行后会给出符合拓扑排序的课程安排计划。二、基本要求1、选择合适的存储结构,建立有向无环图,并输出该图;2、实现拓扑排序算法;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)直到课程序列中所有元素均被遍历,则该序列是拓扑序列,否则不是拓扑序列。wilyes11收集博客(与学习无关):四、数据结构1、链式队列的存储类型为:typedefintElemType;typedefstructQNode{ElemTypedata;structQNode*next;}QNode,*QueuePtr;typedefstruct{QueuePtrfront;QueuePtrrear;}LinkQueue;2、图的类型(邻接表存储结构)为:typedefcharVertexType[20];//顶点信息(名称)typedefstructArcNode//链表结点{intvexpos;//该弧所指向的顶点在数组中的位置structArcNode*next;//指向当前起点的下一条弧的指针}ArcNode;typedefstructVNode//头结点{VertexTypename;//顶点信息(名称)intindegree;//顶点入度ArcNode*firstarc;//指向当前顶点的第一条弧的指针}VNode,AdjList[MAX_VERTEX_NUM];typedefstruct{AdjListvexhead;//邻接表头结点数组intvexnum,arcnum;//图的顶点数和弧数}ALGraph;五、模块划分1、链式队列操作1)voidInitQueue(LinkQueue*Q)功能:初始化链式队列参数:*Q待初始化的队列2)intQueueEmpty(LinkQueueQ)功能:判断空队列参数:Q待判断的队列返回值:队列为空返回1;队列非空返回03)voidEnQueue(LinkQueue*Q,ElemTypee)功能:元素入队列参数:*Q待操作的队列;e要入队列的元素4)voidDeQueue(LinkQueue*Q,ElemType*e)wilyes11收集博客(与学习无关):功能:元素出队列参数:*Q待操作的队列;*e记录出队列元素的变量2、有向图(DAG)邻接表存储结构(ALG)的操作1)intLocateVex(ALGraphG,VertexTypev)功能:顶点在头结点数组中的定位参数:G待操作的图;v要在图中定位的顶点返回值:顶点存在则返回在头结点数组中的下标;否则返回图的顶点数2)intCreateGraph(ALGraph*G)功能:建立图函数内包含了由用户输入顶点数、弧数、顶点以及弧的操作参数:*G待操作的图返回值:图建立成功返回1;图建立失败返回0错误判断:包含顶点数、弧数是否正确的判断;包含用户输入的弧的顶点是否存在的判断3)voidPrintGraph(ALGraphG)功能:输出有向图参数:G待输出的图4)intCreateGraph2(ALGraph*G)功能:建立预置课程图(输出函数内预置课程信息,并自动建立有向图)参数:*G待操作的图返回值:图建立成功返回1;图建立失败返回0错误判断:包含顶点数、弧数是否正确的判断包含弧的顶点是否存在的判断5)voidPrintGraph2(ALGraphG)功能:输出预置课程图参数:G待输出的图3、拓扑排序及拓扑检测算法1)voidTopologicalSort(ALGraphG)功能:实现拓扑排序参数:G待进行拓扑排序的图错误判断:包含有向图是否有环的判断2)voidTopSortCheck(ALGraphG)功能:运用拓扑排序的思想检测教学计划函数内包含了由用户输入待检测的课程序列的操作参数:G待操作的图错误判断:包含用户输入的课程是否存在的判断wilyes11收集博客(与学习无关):包含不是拓扑序列的原因(该课程有多少个先决课程未学)4、主函数voidmain()功能:主函数利用while语句和switch语句实现菜单化调用函数六、源程序#includestdlib.h#includestdio.h#includestring.h/*******************************************//*以下为链式队列操作*//*******************************************//*定义链式队列类型*/typedefintElemType;typedefstructQNode{ElemTypedata;structQNode*next;}QNode,*QueuePtr;typedefstruct{QueuePtrfront;QueuePtrrear;}LinkQueue;/*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;elsereturn0;}/*3.入队列*/voidEnQueue(LinkQueue*Q,ElemTypee){QueuePtrp;p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(0);p-data=e;p-next=NULL;wilyes11收集博客(与学习无关):=p;Q-rear=p;}/*4.出队列*/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);}}/****************************************************//*以下为有向图(DAG)邻接表存储结构(ALG)的操作*//****************************************************/#defineMAX_VERTEX_NUM20//最大顶点个数typedefcharVertexType[20];//顶点信息(名称)/*图的类型定义(邻接表存储结构)*/typedefstructArcNode//链表结点{intvexpos;//该弧所指向的顶点在数组中的位置structArcNode*next;//指向当前起点的下一条弧的指针}ArcNode;typedefstructVNode//头结点{VertexTypename;//顶点信息(名称)intindegree;//顶点入度ArcNode*firstarc;//指向当前顶点的第一条弧的指针}VNode,AdjList[MAX_VERTEX_NUM];typedefstruct{AdjListvexhead;//邻接表头结点数组intvexnum,arcnum;//图的顶点数和弧数}ALGraph;/*5.顶点在头结点数组中的定位*/intLocateVex(ALGraphG,VertexTypev){inti;for(i=0;iG.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;wilyes11收集博客(与学习无关):(\n输入有向图顶点数和弧数vexnum,arcnum:);//输入顶点数和弧数scanf(%d,%d,&(*G).vexnum,&(*G).arcnum);//输入并判断顶点数和弧数是否正确if((*G).vexnum0||(*G).arcnum0||(*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).ve
本文标题:拓扑排序(算法与数据结构课程设计)
链接地址:https://www.777doc.com/doc-7314715 .html