设计题目:示例数据:输入:学期数:5,课程数:12,课程间的先后关系数:16,课程的代表值:v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12。
课程间两两间的先后关系:v1 v2,v1 v3, v1 v4,v1 v12,v2 v3,v3 v5,v3 v7,v3 v8,v4 v5, v5 v7,v6 v8,v9 v10, v9 v11 , v9 v12,v10 v12,v11 v6输出:第1学期应学的课程:v1 v9第2学期应学的课程:v2 v4 v10 v11第3学期应学的课程:v3 v6 v12第4学期应学的课程:v5 v8第5学期应学的课程:v7一需求分析1.1 引言通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。
简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
离散数学中关于偏序和全序的定义:若集合X上的关系是R,且R是自反的、反对称的和传递的,则称R是集合X上的偏序关系。
设R是集合X上的偏序(Partial Order),如果对每个x,y属于X必有xRy 或 yRx,则称R是集合X上的全序关系。
比较简单的理解:偏序是指集合中只有部分成员可以比较,全序是指集合中所有的成员之间均可以比较。
一般应用:拓扑排序常用来确定一个依赖关系集中,事物发生的顺序。
例如,在日常工作中,可能会将项目拆分成A、B、C、D四个子部分来完成,但A依赖于B和D,C依赖于D。
为了计算这个项目进行的顺序,可对这个关系集进行拓扑排序,得出一个线性的序列,则排在前面的任务就是需要先完成的任务。
1.2 拓扑排序的了解①.问题的描述在AOV网中为了更好地完成工程,必须满足活动之间先后关系,需要将各活动排一个先后次序即为拓扑排序。
拓扑排序可以应用于教学计划的安排,根据课程之间的依赖关系,制定课程安排计划。
按照用户输入的课程数,课程间的先后关系数目以及课程间两两间的先后关系,程序执行后会给出符合拓扑排序的课程安排计划②. 拓扑排序进行教学计划安排检验理论基础为实现对无权值有向图进行拓扑排序,输出拓扑序列,先考虑如何存储这个有向图。
拓扑排序的过程中要求找到入度为0的顶点,所以要采用邻接表来存储有向图,而要得到邻接表,则先要定义有向图的邻接矩阵结构,再把邻接矩阵转化成邻接表。
在具体实现拓扑排序的函数中,根据规则,当某个顶点的入度为0(没有前驱顶点)时,就将此顶点输出,同时将该顶点的所有后继顶点的入度减1,为了避免重复检测入度为0的顶点,设立一个栈St,以存放入度为0的顶点。
③.拓扑排序算法void TopologicalSort(ALGraph G),大体思想为:1)遍历有向图各顶点的入度,将所有入度为零的顶点入队列;2)队列非空时,输出一个顶点,并对输出的顶点数计数;3)该顶点的所有邻接点入度减一,若减一后入度为零则入队列;4)重复2)、3),直到队列为空,若输出的顶点数与图的顶点数相等则该图可拓扑排序,否则图中有环。
1.3 查阅相关资料,完成程序的实现二总体设计拓扑排序:三详细设计3.1 算法设计分析拓扑排序时有向图的一种重要运算。
在课表排序中,每门课都有多种关系:、(一)先后关系,即必须在一门课学完后,才能开始学习另一门课;(二)在一类课之间没有次序要求,即两门课可以同时学习,互不影响。
将AOV 网络中的各个顶点排列成一个线性有序序列,使得所有的要求的前趋、后趋关系都能得到满足。
在AOV网络进行拓扑排序的方法:(一)从中选择一个没有前趋的顶点,并把它输出;(二)从网络中删去该顶点和从该顶点出发的所有有向边;重复执行上述两步,直到网中所有的顶点都被输出3.2 源代码#include <malloc.h>#include <stdio.h>#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define STACKINCREMENT 10#define MAX_VERTEX_NUM 20#define STACK_INIT_SIZE 100typedef int Status;typedef int SElemType;int indegree[20]={0};typedef struct {SElemType *base;SElemType *top;int stacksize;}SqStack;typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode;typedef struct VNode{char data[10];ArcNode *firstarc;}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;}ALGraph;Status InitStack(SqStack &S){S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!S.base)return ERROR;S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}Status Push(SqStack &S,SElemType e){if(S.top-S.base>=S.stacksize){S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));if(!S.base)return ERROR;S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}Status Pop(SqStack &S,SElemType &e)if(S.top==S.base)return ERROR;e=*--S.top;return OK;}Status StackEmpty(SqStack S){if(S.top==S.base)return TRUE;else return FALSE;}Status CreateDG(ALGraph &G){int i,l,v,w,vex;printf("\t请输入学期数目(小于等于8):\t");scanf("%d",&l);if(l>8){printf("\tWarning!\n\t学期数目必须小于等于8 ! 请重新输入:");scanf("%d",&l);}printf("\t请输入课程数目(小于20):");scanf("%d",&vex);if(vex>=20){printf("\tWarning! \n\t课程数目必须小于20 ! 请重新输入:");scanf("%d",&vex);}G.vexnum=vex;printf("\t请输入课程间的先后关系数:");scanf("%d",&G.arcnum);printf("请输入课程的代表值(课程名的长度小于等于10个字符):");for(i=0;i<G.vexnum;i++){scanf("%s",&G.vertices[i].data);G.vertices[i].firstarc = NULL;}printf("请注意v1=1,v2=2,v3=3,v4=4,c5=5,v6=6,v7=7,v8=8,v9=9,v10=10,v11=11,v12=12\n");printf("请输入课程间两两间的先后关系:");for(i=0;i<G.arcnum;i++){scanf("%d %d,",&v, &w);ArcNode *p= new ArcNode;if(!p) return ERROR;p->adjvex=w-1;p->nextarc=G.vertices[v-1].firstarc;G.vertices[v-1].firstarc=p;}return OK;}void FindInDegree(ALGraph G){ArcNode* p;for(int i=0;i<G.vexnum;i++){p=G.vertices[i].firstarc;while(p){for(int j=0;j<G.vexnum;j++)if(p->adjvex==j)indegree[j]++;p=p->nextarc;}}}Status TopologicalSort(ALGraph G){SqStack S1,S2;ArcNode* p;int i,count,k;FindInDegree(G);InitStack(S1);InitStack(S2);for(i=0;i<G.vexnum;++i)if(!indegree[i])Push(S1,i);count=0;while(!StackEmpty(S1)){printf("第%d学期应学的课程:",count+1);while(!StackEmpty(S1)){Pop(S1,i);printf("%s ",G.vertices[i].data);Push(S2,i);}printf("\n");count++;while(!StackEmpty(S2)){Pop(S2,i);for(p=G.vertices[i].firstarc;p;p=p->nextarc){k=p->adjvex;if(!(--indegree[k]))Push(S1,k);}}}if(count<G.vexnum)return ERROR;else return OK;}int main(){printf("*********************************************************************** \n");printf(" 教学计划检验程序(拓扑排序) \n\n");printf(" v1 程序设计基础 v2 离散数学 v3 数据结构\n");printf(" v4 汇编语言 v5 语言设计与分析 v6 计算机原理\n");printf(" v7 编译原理 v8 操作系统 v9 高等数学\n");printf(" v10 线性代数 v11 普通物理 v12 数值分析\n\n");printf("*********************************************************************** \n");ALGraph T;CreateDG (T);TopologicalSort(T);return 0;}3.3 调试与分析1.运行程序打开界面如下图,并根据提示,输入学期数目:2.输入出错时显示如下:3.输入正确则继续,根据界面提示输入课程的代表值:4.根据界面提示输入课程间两两间的先后关系:5 输入课程间两两间的先后关系后,则输出每学期应学的课程:6 完美运行结果:四总结经过近三个星期的不断的学习与努力,有收获,有挫折,终于完成了《教学计划安排检验程序(拓扑排序)》的数据结构课程设计。