拓扑排序-数据结构实验
数据结构(牛小飞)3 拓扑排序

2021/8/5
25
5
拓扑排序-定义
拓扑排序是对有向无圈图的顶点的一种排序,使 得如果存在一条从vi到vj的路径,那么在排序中vj 就出现在vi的后面。
✓ 显然,如果图中含有圈,那么拓扑排序是不可能的, 因为对于圈上的两个顶点v和w,v优先于w同时w又优 先于v。
2021/8/5
6
拓扑排序-举例
B
A
D
C
不能求得它的拓扑有序序列。
// 对尚未访问的顶点调用DFS
}
while(!Empty(S)) //输出拓扑排序的结果
System.out.print(S.pop());
} 2021/8/5
21
拓扑排序-方法2
void DFS-T(int v) { // 从顶点v出发,深度优先搜索遍历连通图 vertexs[v].visited = true; for(w=FirstAdjVex(v);w>=0; w=NextAdjVex(v,w)) { if (!vertexs[w].visited) DFS-T(w); } // 对v的尚未访问的邻接顶点w递归调用DFS-T S.push(v); //顶点v的DFS函数执行完毕
q.enqueue(v);
while (!q.isEmpty( ) { //如果队列非空
…………
}
if (counter!=NUM_VERTICES) //有圈
throw new CycleFoundException( );
}
2021/8/5
15
拓扑排序-方法1
void topsort( ) throws CycleFoundException { …….
} // DFS-T
数据结构排序实验报告

数据结构排序实验报告数据结构排序实验报告引言:数据结构是计算机科学中的重要概念之一,它涉及到数据的组织、存储和操作方式。
排序是数据结构中的基本操作之一,它可以将一组无序的数据按照特定的规则进行排列,从而方便后续的查找和处理。
本实验旨在通过对不同排序算法的实验比较,探讨它们的性能差异和适用场景。
一、实验目的本实验的主要目的是通过实际操作,深入理解不同排序算法的原理和实现方式,并通过对比它们的性能差异,选取合适的排序算法用于不同场景中。
二、实验环境和工具实验环境:Windows 10 操作系统开发工具:Visual Studio 2019编程语言:C++三、实验过程1. 实验准备在开始实验之前,我们需要先准备一组待排序的数据。
为了保证实验的公正性,我们选择了一组包含10000个随机整数的数据集。
这些数据将被用于对比各种排序算法的性能。
2. 实验步骤我们选择了常见的五种排序算法进行实验比较,分别是冒泡排序、选择排序、插入排序、快速排序和归并排序。
- 冒泡排序:该算法通过不断比较相邻元素的大小,将较大的元素逐渐“冒泡”到数组的末尾。
实现时,我们使用了双重循环来遍历整个数组,并通过交换元素的方式进行排序。
- 选择排序:该算法通过不断选择数组中的最小元素,并将其放置在已排序部分的末尾。
实现时,我们使用了双重循环来遍历整个数组,并通过交换元素的方式进行排序。
- 插入排序:该算法将数组分为已排序和未排序两部分,然后逐个将未排序部分的元素插入到已排序部分的合适位置。
实现时,我们使用了循环和条件判断来找到插入位置,并通过移动元素的方式进行排序。
- 快速排序:该算法通过选取一个基准元素,将数组分为两个子数组,并对子数组进行递归排序。
实现时,我们使用了递归和分治的思想,将数组不断划分为更小的子数组进行排序。
- 归并排序:该算法通过将数组递归地划分为更小的子数组,并将子数组进行合并排序。
实现时,我们使用了递归和分治的思想,将数组不断划分为更小的子数组进行排序,然后再将子数组合并起来。
拓扑排序的原理及其实现

拓扑排序的原理及其实现取材自以下材料:/wiki/Topological_sorting/wiki/Hamiltonian_path定义和前置条件:定义:将有向图中的顶点以线性方式进行排序。
即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面。
如果这个概念还略显抽象的话,那么不妨考虑一个非常非常经典的例子——选课。
我想任何看过数据结构相关书籍的同学都知道它吧。
假设我非常想学习一门“机器学习”的课程,但是在修这么课程之前,我们必须要学习一些基础课程,比如:计算机科学概论,C语言程序设计,数据结构,算法等等。
那么这个制定选修课程顺序的过程,实际上就是一个拓扑排序的过程,每门课程相当于有向图中的一个顶点,而连接顶点之间的有向边就是课程学习的先后关系。
只不过这个过程不是那么复杂,从而很自然的在我们的大脑中完成了。
将这个过程以算法的形式描述出来的结果,就是拓扑排序。
那么是不是所有的有向图都能够被拓扑排序呢?显然不是。
继续考虑上面的例子,如果告诉你在选修“计算机科学概论”这门课之前需要你先学习“机器学习”,你是不是会被弄糊涂?在这种情况下,就无法进行拓扑排序,因为它中间存在互相依赖的关系,从而无法确定谁先谁后。
在有向图中,这种情况被描述为存在环路。
因此,一个有向图能被拓扑排序的充要条件就是它是一个有向无环图(DAG:Directed Acyclic Graph)。
偏序/全序关系:偏序和全序实际上是离散数学中的概念。
这里不打算说太多形式化的定义,形式化的定义教科书上或者上面给的链接中就说的很详细。
还是以上面选课的例子来描述这两个概念。
假设我们在学习完了算法这门课后,可以选修“机器学习”或者“计算机图形学”。
这个“或者”表示,学习“机器学习”和“计算机图形学”这两门课之间没有特定的先后顺序。
因此,在我们所有可以选择的课程中,任意两门课程之间的关系要么是确定的(即拥有先后关系),要么是不确定的(即没有先后关系),绝对不存在互相矛盾的关系(即环路)。
图的搜索与应用实验报告(附源码)(word文档良心出品)

哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:图的搜索与应用实验题目:图的深度和广度搜索与拓扑排序设计成绩报告成绩指导老师一、实验目的1.掌握图的邻接表的存储形式。
2.熟练掌握图的搜索策略,包括深度优先搜索与广度优先搜索算法。
3.掌握有向图的拓扑排序的方法。
二、实验要求及实验环境实验要求:1.以邻接表的形式存储图。
2.给出图的深度优先搜索算法与广度优先搜索算法。
3.应用搜索算法求出有向图的拓扑排序。
实验环境:寝室+机房+编程软件(NetBeans IDE 6.9.1)。
三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)数据类型定义:template <class T>class Node {//定义边public:int adjvex;//定义顶点所对应的序号Node *next;//指向下一顶点的指针int weight;//边的权重};template <class T>class Vnode {public:T vertex;Node<T> *firstedge;};template <class T>class Algraph {public:Vnode<T> adjlist[Max];int n;int e;int mark[Max];int Indegree[Max];};template<class T>class Function {public://创建有向图邻接表void CreatNalgraph(Algraph<T>*G);//创建无向图邻接表void CreatAlgraph(Algraph<T> *G);//深度优先递归搜索void DFSM(Algraph<T>*G, int i);void DFS(Algraph<T>* G);//广度优先搜索void BFS(Algraph<T>* G);void BFSM(Algraph<T>* G, int i);//有向图的拓扑排序void Topsort(Algraph<T>*G);/得到某个顶点内容所对应的数组序号int Judge(Algraph<T>* G, T name); };主程序流程图:程序开始调用关系:主函数调用五个函数 CreatNalgraph(G)//创建有向图 DFS(G) //深度优先搜索 BFS(G) //广度优先搜索 Topsort(G) //有向图拓扑排序 CreatAlgraph(G) //创建无向图其中 CreatNalgraph(G) 调用Judge(Algraph<T>* G, T name)函数;DFS(G)调用DFSM(Algraph<T>* G , int i)函数;BFS(G) 调用BFSM(Algraph<T>* G, int k)函数;CreatAlgraph(G) 调选择图的类型无向图有向图深 度 优 先 搜 索广度优先搜索 深 度 优 先 搜 索 广度优先搜索拓 扑 排 序程序结束用Judge(Algraph<T>* G, T name)函数。
数据结构之的拓扑排序算法拓扑排序算法的实现和性能分析

数据结构之的拓扑排序算法拓扑排序算法的实现和性能分析数据结构之拓扑排序算法拓扑排序算法的实现和性能分析拓扑排序是一种常用的图算法,用于对有向无环图(DAG)进行排序。
拓扑排序的主要应用包括任务调度、编译顺序、依赖关系管理等方面。
本文将介绍拓扑排序算法的实现及其性能分析。
一、拓扑排序算法的实现拓扑排序算法一般采用深度优先搜索(DFS)或广度优先搜索(BFS)来实现。
下面将以DFS实现为例进行介绍。
1. 创建图数据结构在进行拓扑排序之前,首先需要创建图的数据结构。
可以使用邻接表或邻接矩阵来表示图。
以邻接表为例,可以使用一个字典来表示每个节点和其相邻节点的关系。
2. 初始化标记数组为了保证每个节点只被访问一次,需要使用一个标记数组来记录节点的访问状态。
可以使用布尔数组或整数数组来表示,将未访问的节点标记为false或0,已访问的节点标记为true或1。
3. 实现拓扑排序函数拓扑排序函数的主要功能是对图进行遍历,并将节点按照拓扑排序的顺序输出。
拓扑排序函数通常使用递归的方式实现。
4. 输出排序结果拓扑排序算法完成后,可以将排序的结果输出。
按照拓扑排序的定义,输出的结果应该是一个拓扑有序的节点列表。
二、拓扑排序算法的性能分析拓扑排序算法的性能取决于图的规模和结构。
下面将从时间复杂度和空间复杂度两个方面进行性能分析。
1. 时间复杂度分析拓扑排序算法的时间复杂度主要取决于图的节点数和边数。
在最坏情况下,每个节点都需要遍历一次,而每个节点的边数是有限的,所以拓扑排序的时间复杂度为O(V+E),其中V表示节点数,E表示边数。
2. 空间复杂度分析拓扑排序算法的空间复杂度主要取决于存储图和标记数组的空间。
在使用邻接表表示图时,需要额外的空间来存储每个节点及其相邻节点的关系。
同时,需要使用标记数组来记录节点的访问状态。
所以拓扑排序的空间复杂度为O(V+E+V),即O(V+E),其中V表示节点数,E表示边数。
三、总结拓扑排序是一种常用的图算法,可以对有向无环图进行排序。
数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。
功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。
按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。
数据结构之拓扑排序算法详解

数据结构之拓扑排序算法详解拓扑排序算法是一种常用于有向无环图(DAG)的排序算法,它可以将图中的顶点按照一定的顺序进行排序,使得图中任意一条有向边的起点在排序结果中都排在终点的前面。
在实际应用中,拓扑排序算法常用于解决任务调度、依赖关系分析等问题。
本文将详细介绍拓扑排序算法的原理、实现方法以及应用场景。
### 一、拓扑排序算法原理拓扑排序算法的原理比较简单,主要包括以下几个步骤:1. 从DAG图中选择一个入度为0的顶点并输出。
2. 从图中删除该顶点以及以该顶点为起点的所有有向边。
3. 重复步骤1和步骤2,直到图中所有顶点都被输出。
### 二、拓扑排序算法实现下面以Python语言为例,给出拓扑排序算法的实现代码:```pythondef topological_sort(graph):in_degree = {v: 0 for v in graph}for u in graph:for v in graph[u]:in_degree[v] += 1queue = [v for v in graph if in_degree[v] == 0] result = []while queue:u = queue.pop(0)result.append(u)for v in graph[u]:in_degree[v] -= 1if in_degree[v] == 0:queue.append(v)if len(result) == len(graph):return resultelse:return []# 测试代码graph = {'A': ['B', 'C'],'B': ['D'],'C': ['D'],'D': []}print(topological_sort(graph))```### 三、拓扑排序算法应用场景拓扑排序算法在实际应用中有着广泛的应用场景,其中包括但不限于以下几个方面:1. 任务调度:在一个任务依赖关系图中,拓扑排序可以确定任务的执行顺序,保证所有任务按照依赖关系正确执行。
数据结构拓扑排序实验报告

数据结构拓扑排序实验报告正文:一、实验目的本实验旨在通过实现拓扑排序算法来加深对数据结构中图的相关概念的理解,掌握拓扑排序的具体步骤与实现方法。
二、实验原理拓扑排序是一种对有向无环图进行排序的算法,它可以将有向无环图的顶点按照线性的顺序排列出来,使得对于任何一个有向边(u, v),都有顶点 u 在排列中出现在顶点 v 之前。
拓扑排序常用于表示图中的依赖关系,如任务调度、编译顺序等场景。
三、实验步骤1. 构建有向图根据实际需求构建有向图,可以使用邻接表或邻接矩阵等数据结构来表示有向图。
2. 执行拓扑排序算法利用拓扑排序算法对构建的有向图进行排序,可选择使用深度优先搜索(DFS)或广度优先搜索(BFS)等算法实现。
3. 输出排序结果将排序后的顶点按照线性的顺序输出,得到拓扑排序的结果。
四、实验结果与分析1. 实验数据以图 G = (V, E) 的顶点集合 V 和边集合 E,构建了如下的有向图:V = {A, B, C, D, E, F}E = {(A, C), (B, C), (C, D), (D, E), (E, F)}2. 拓扑排序结果经过拓扑排序算法的处理,得到的拓扑排序结果如下: A, B, C, D, E, F3. 结果分析可以看出,根据有向图的依赖关系,拓扑排序算法能够将顶点按照合理的顺序进行排序。
拓扑排序的结果可以作为图中顶点的执行顺序,具有重要的应用价值。
五、实验总结通过本次实验,我们深入学习了拓扑排序算法,并成功实现了拓扑排序的过程。
拓扑排序在图论和数据结构中具有广泛的应用,对于理解和解决与图相关的问题具有重要意义。
六、附件本文档没有涉及附件内容。
七、法律名词及注释本文档没有涉及法律名词及注释。
拓扑排序实验报告

拓扑排序实验报告一、引言拓扑排序是一种图论中重要的算法,用于对有向无环图(DAG)中的顶点进行排序。
在该实验中,我们将对拓扑排序的算法进行实现,并对其进行性能分析和评估。
二、实验目的1. 了解拓扑排序的基本概念和算法;2. 实现拓扑排序的算法;3. 进行性能分析和评估,探究其时间复杂度。
三、实验方法1. 根据给定的有向无环图构建邻接表;2. 使用深度优先搜索(DFS)算法实现拓扑排序;3. 对不同规模的图进行拓扑排序,并记录所用时间;4. 分析并评估算法的性能。
四、实验过程1. 构建邻接表:根据给定的有向无环图,我们首先构建它的邻接表表示。
邻接表中的每个节点表示一个顶点,其指针指向该顶点的所有后继节点。
2. 深度优先搜索拓扑排序:从图中选择一个未被访问过的顶点作为起始点,递归地遍历其所有后继节点,直到所有的顶点都被访问过。
通过递归的方式,可以得到一个拓扑排序的结果。
3. 性能分析和评估:我们使用不同规模的图进行拓扑排序,并记录所用的时间。
根据实验数据,分析算法的时间复杂度,并评估其性能。
五、实验结果我们使用了10个不同规模的有向无环图进行了拓扑排序,并记录了所用的时间。
实验结果表明,随着图规模的增加,算法的时间复杂度也随之增加。
具体结果如下:图规模时间(ms)5 0.00110 0.00350 0.012100 0.025250 0.067500 0.135750 0.2561000 0.3872000 0.8055000 2.016通过以上实验结果,我们可以看出,拓扑排序算法的时间复杂度约为O(n + m),其中n为图中的顶点数,m为图中的边数。
实验结果与理论分析相符。
六、实验总结在本次实验中,我们实现了拓扑排序的算法,并进行了性能分析和评估。
通过实验结果可以看出,随着图规模的增加,算法的时间复杂度也随之增加。
拓扑排序算法是一种非常有用的算法,广泛应用于各个领域,例如编译器的依赖关系分析和任务调度等。
拓扑排序讲解+例题

拓扑排序讲解+例题对⼀个==有向⽆环图(Directed Acyclic Graph简称DAG)==G进⾏拓扑排序,是将G中所有顶点排成⼀个线性序列,使得图中任意⼀对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。
通常,这样的线性序列称为满⾜拓扑次序(Topological Order)的序列,简称拓扑序列。
简单的说,由某个集合上的⼀个偏序得到该集合上的⼀个全序,这个操作称之为拓扑排序。
⽐如说给定若⼲个两个元素之间的⼤⼩关系,要转换成所有元素的总体⼤⼩关系,就可以⽤拓扑排序来处理下⾯给出的例题就是这个样⼦关于拓扑排序还有⼀种⽤法->判断给定的有向图中是否存在环下⾯来说明⼀下拓扑排序的相关步骤:(默认已经将图存好)⾸先统计所有点的⼊度,然后将所有点⼊度为0的所有点放进队列(根据题⽬特殊要求也可以使⽤优先队列)然后采取像BFS那样的⽅式,当队列⾮空的时候,始终取队列头端的⼀个元素,并将这个元素记录下来之后pop掉,把这个点(⽐如说是点P)放进⽤来存储拓扑序列的不定长数组vector中,然后遍历和这个点相连的所有点,并将与点P相连的所有点的⼊度减少1(换句话说讲点P去掉之后,他的指向关系就会消失,并且以他为起点的所有点的⼊度都会减⼩1),如果这个点的⼊度刚好为0,那么正好可以将这个点继续放到队列中,如此反复伪代码如下void top_sort(){for(int i=1;i<=n;i++){if(⼊读为0) que.push(i);}while(que.size()){int top = que.top()/que.front();que.pop();vet.push_back(这个点->top);for(int i=1;i<=n;i++){///在数据范围⾜够⼩的情况下可以直接采取⼆维数组存图/// gra[i][j] == 1表⽰有⼀条从i指向j的边,反之没有if(相连){deg[i]--;if(deg[i] == 0) que.push(i);}}}}下⾯是⽐较常⽤的⼩模板:priority_queue <int, vector<int>, greater<int> >litt;int dege[507];int n,m;int gra[507][507];vector<int>vet;void top_sort(){for(int i=1;i<=n;i++){if(dege[i] == 0) litt.push(i);}while(litt.size()){int tp = litt.top();litt.pop();vet.push_back(tp);for(int i=1;i<=n;i++){if(gra[tp][i]){dege[i] --;if(dege[i] == 0) litt.push(i);}}}}下⾯来看例题:题⽬描述有N个⽐赛队(1<=N<=500),编号依次为1,2,3,。
拓扑排序实训报告

一、实训目的通过本次拓扑排序实训,掌握拓扑排序的基本原理和算法实现方法,能够运用拓扑排序解决实际问题,提高自己在数据结构和算法方面的应用能力。
二、实训内容1. 拓扑排序原理及算法拓扑排序是一种针对有向无环图(DAG)的排序方法,它将图中的顶点按照某种顺序排列,使得图中所有的有向边都满足方向要求。
具体来说,拓扑排序要求在有向边(u,v)中,顶点u必须在顶点v之前。
拓扑排序的基本思想是:从入度为0的顶点开始,将其加入拓扑序列,然后删除该顶点及其所有出边,更新其他顶点的入度。
重复这个过程,直到所有顶点都被加入拓扑序列。
2. 拓扑排序算法实现本次实训中,我们将学习两种拓扑排序算法实现:(1)基于邻接矩阵的拓扑排序首先,我们使用邻接矩阵表示有向图。
然后,遍历邻接矩阵,找出所有入度为0的顶点,将其加入拓扑序列。
接着,删除该顶点及其所有出边,更新其他顶点的入度。
重复这个过程,直到所有顶点都被加入拓扑序列。
(2)基于邻接表的拓扑排序邻接表是一种链式存储结构,它将图中所有顶点存储在一个链表中,每个顶点对应一个链表,链表中存储与该顶点相连的所有顶点。
基于邻接表的拓扑排序算法如下:(1)初始化拓扑序列为空,入度数组为顶点数大小的数组,所有元素的值设为0。
(2)遍历邻接表,找出所有入度为0的顶点,将其加入拓扑序列,并将入度数组中相应元素的值减1。
(3)删除拓扑序列中的顶点及其所有出边,更新入度数组。
(4)重复步骤(2)和(3),直到拓扑序列不为空。
三、实训过程1. 阅读拓扑排序相关资料,了解其原理和算法实现方法。
2. 使用C++编写基于邻接矩阵的拓扑排序程序,实现图数据的构建、拓扑排序和输出拓扑序列。
3. 使用C++编写基于邻接表的拓扑排序程序,实现图数据的构建、拓扑排序和输出拓扑序列。
4. 对比两种算法的优缺点,分析其在实际应用中的适用场景。
5. 运行程序,测试不同图数据的拓扑排序结果,验证程序的正确性。
四、实训总结1. 通过本次实训,我们掌握了拓扑排序的基本原理和算法实现方法,提高了自己在数据结构和算法方面的应用能力。
数据结构-chap7 (4)AOV网与拓扑排序

}//for }//while if (count<G.vexnum) return ERROR; //该有向图有回路 else return OK; }//TopologicalSort
自测题2 AOV-网的拓扑排序
v2 v1 v3 v4 v5 v6 v1 v2
1
3 0 1 0 3 S.top S.base
5 4
1
2 3
3
2 1 4 0 2
C2
1
0
5 0
1
4
5
C3
C4
C5
C3 0 C4
5 0
C5 0
while(! StackEmpty(S)){ Pop(S, i); printf(i, G. vertices[i].data); ++count; for (p=G.vertices[i].firstarc; p; p=p->nextarc) { k = p->adjvex; if ( !(- -indegree[k]) ) Push(S, k); }//for }//while data firstarc C0 1 3 0 栈S C1 5 0
Status TopologicalSort(ALGraph G) { FindInDegree(G, indegree); //求各顶点入度indegree[0..vexnum-1] InitStack(S); for(i=0; i<G. vexnum; ++i) if (! indegree[i]) Push(S, i); //入度为0顶点的编号进栈 count = 0; //对输出顶点计数 count=6 while(! StackEmpty(S)){ Pop(S, i); //从零入度顶点栈S 栈顶,获得一入度为零的顶点i printf(i, G. vertices[i].data); ++count; //输出i号顶点的数据,并计数 for (p=G. vertices[i]. firstarc; p; p=p->nextarc) { k = p->adjvex; if ( !(- -indegree[k]) ) Push(S, k); //对i号顶点邻接到的 每个顶点入度减1
数据结构拓扑排序实验报告

数据结构拓扑排序实验报告数据结构拓扑排序实验报告一、引言本实验旨在通过实现拓扑排序算法,对给定的有向图进行排序操作。
拓扑排序是一种对有向图进行排序的算法,根据有向边的方向,将图中的节点排列成线性序列,并满足任意一条边的起点在序列中位于终点之前的要求。
二、实验目的1.理解拓扑排序的概念及原理;2.掌握拓扑排序的具体实现方法;3.实现拓扑排序算法,并对给定的有向图进行排序实验。
三、理论知识1.有向图:由一组顶点和一组有向边组成的图结构,每条有向边连接两个顶点,有方向性。
2.有向边:连接有向图中两个顶点的边,表明了两个顶点之间的关系,有起点和终点之分。
3.入度:指向某一顶点的有向边的数量。
4.拓扑排序:一种对有向图进行排序的算法,要求在排序结果中,任意一条边的起点在序列中位于终点之前。
四、实验步骤1.创建图的数据结构,包括顶点和有向边的表示;2.读入有向图的顶点和边的信息,并构建图的结构;3.计算每个顶点的入度,并初始化拓扑排序结果序列;4.选择一个入度为0的顶点,将其加入拓扑排序结果序列,并将其所连接的顶点的入度减1;5.重复步骤4,直到所有顶点被加入拓扑排序结果序列;6.输出最终的拓扑排序结果。
五、实验结果- 给定的有向图:- 图片附件1:有向图示意图- 通过拓扑排序算法得到的排序结果:- 顶点A →顶点B →顶点C →顶点D →顶点E六、实验分析与总结在本次实验中,我们成功实现了拓扑排序算法,并对给定的有向图进行了排序。
通过实验结果可以看出,拓扑排序可以将有向图中的节点按照依赖关系进行排序。
通过拓扑排序,我们可以找到一个满足依赖关系的节点序列,用于解决诸如任务调度、依赖关系分析等问题。
七、附件- 图片附件1:有向图示意图八、法律名词及注释1.有向图:在图论中,有向图是由一组顶点和一组有向边组成的图结构,每条边连接两个顶点,并有方向性。
2.拓扑排序:一种对有向图进行排序的算法,要求在排序结果中,任意一条边的起点在序列中位于终点之前。
数据结构-拓扑排序介绍

成绩14信计 2015-2016(一)数据结构课程设计设计题目拓扑排序设计时间——学生姓名冯佳君学生学号20140401105所在班级14信计 1指导教师刘风华徐州工程学院数学与物理科学学院一、需求剖析1.问题描绘本次课程设计题目是:用毗邻表结构图而后进行拓扑排序,输出拓扑排序序列。
拓扑排序的基本思想为:1)从有向图中选一个无前驱的极点输出;2)将此极点和以它为起点的弧删除;3)重复 1) 、 2) 直到不存在无前驱的极点;4)若此时输出的极点数小于有向图中的极点数,则说明有向图中存在回路,不然输出的极点的次序即为一个拓扑序列。
2.拓扑排序有向图拓朴排序算法的基本步骤以下:1 )从图中选择一个入度为0 的极点,输出该极点;2 )从图中删除该极点及其有关系的弧,调整被删弧的弧头结点的入度(入度-1 );3)重复履行 1)、 2)直到全部极点均被输出,拓朴排序达成或许图中再也没有入度为 0 的极点(此种状况说明原有向图含有环)。
3.基本要求(1)输入的形式和输入值的范围;第一是输入要排序的极点数和弧数,都为整型,中间用分开符分开;再输入各极点的值,为正型,中间用分开符分开;而后输入各条弧的两个极点值,先输入弧头,再输入弧尾,中间用分开符分开,输入的值只好是开始输入的极点值不然系统会提示输入的值的极点值不正确,请从头输入,只需持续输入正确的值就行。
(2)输出的形式;第一输出成立的毗邻表,而后是最后各极点的出度数,再是拓扑排序的序列,而且每输出一个极点,就会输出一次各极点的入度数。
(3)程序所能达到的功能;因为该程序是求拓扑排序,所以算法的功能就是要输出拓扑排序的序列,在一个有向图中,若用极点表示活动,有向边就表示活动间先后次序,那么输出的拓扑序列就表示各极点间的关系为反应出各点的储存结构,以毗邻表储存并输出各极点的入度。
二、纲要设计1.算法顶用到的全部各样数据种类的定义在该程序顶用毗邻表作为图的储存结构。
数据结构:第7章 图4-拓扑排序和关键路径

拓扑排序算法
拓扑排序方法: (1)在AOV网中选一个入度为0的顶点(没有前驱) 且输出之; (2)从AOV网中删除此顶点及该顶点发出来的所 有有向边; (3)重复(1)、(2)两步,直到AOV网中所有 顶点都被输出或网中不存在入度为0的顶点。
从拓扑排序步骤可知,若在第3步中,网中所有顶 点都被输出,则表明网中无有向环,拓扑排序成功。 若仅输出部分顶点,网中已不存在入度为0的顶点, 则表明网中有有向环,拓扑排序不成功。
拓扑序列:C1--C2--C3 (3)
C12 C9 C10
C7 C8 C6
C11
拓扑序列:C1--C2--C3--C4 (4)
C7
C12
C12
C8
C8 C9 C10
C6
C9 C10
C6
C11
C11 拓扑序列:C1--C2--C3--C4--C5
(5)
拓扑序列:C1--C2--C3--C4--C5--C7 (6)
在 (b)中,我们用一种有向图来表示课程开设
拓扑排序
1.定义 给出有向图G=(V,E),对于V中的顶点的线性序列 (vi1,vi2,...,vin),如果满足如下条件:若在G中从 顶点 vi 到vj有一条路径,则在序列中顶点vi必在 顶点 vj之前;则称该序列为 G的一个拓扑序列。 构造有向图的一个拓扑序列的过程称为拓扑排序。 2.说明 (1)在AOV网中,若不存在回路,则所有活动可排成 一个线性序列,使得每个活动的所有前驱活动都排 在该活动的前面,那么该序列为拓扑序列. (2)拓扑序列不是唯一的.
2.AOV网实际意义
现代化管理中, 通常我们把计划、施工过程、生产流程、 程序流程等都当成一个工程,一个大的工程常常被划分 成许多较小的子工程,这些子工程称为活动。在整个工 程实施过程中,有些活动开始是以它的所有前序活动的 结束为先决条件的,必须在其它有关活动完成之后才能 开始,有些活动没有先决条件,可以 安排在任意时间开 始。AOV网就是一种可以形象地反映出整个工程中各个 活动之间前后关系的有向图。例如,计算机专业学生的 课程开设可看成是一个工程,每一门课程就是工程中的 活动,下页图给出了若干门所开设的课程,其中有些课 程的开设有先后关系,有些则没有先后关系,有先后关 系的课程必须按先后关系开设,如开设数据结构课程之 前必须先学完程序设计基础及离散数学,而开设离散数 学则必须先并行学完数学、程序设计基础课程。
数据结构课程设计拓扑排序(顺序,逆序输出)

目录一.需求分析说明 (1)二.概要设计说明 (1)三.详细设计说明 (2)四.调试分析 (6)五.用户使用说明 (6)六.课程设计总结 (7)七.测试结果 (8)八.参考书目 (9)九. 附录 (10)一、需求分析说明为了更好的学习数据结构,深刻理解数据结构在解决实际问题中的应用,体会其重要性,熟练掌握线性表、栈和队列、串、数组、树、图等常用的数据结构,熟悉各自的特点和应用场合。
同时锻炼自己独立分析理解问题的能力,学会根据不同的问题选择合适的数据结构,然后结合适当的算法解决问题。
锻炼自己的设计和编写程序的技巧,进一步调试和测试自己所写的程序,使其功能更加完善,养成较好的编写程序习惯。
提高综合运用所学的理论知识和方法独立分析和解决问题的能力,训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。
本课程设计的目的就是要达到理论与实际应用相结合,使同学们能够根据数据对象的特性,学会数据组织的方法,能把现实世界中的实际问题在计算机内部表示出来,并培养基本的、良好的程序设计技能。
设计的基本要求:1)选择邻接表作为有向图的存储结构模拟整个过程,并输出拓扑排序的顶点序列。
2)给出逆向的拓扑有序序列。
二、概要设计说明2.1 算法思想采用邻接表存储结构实现有向图;有向图需通过顶点数、边数、顶点以及边等信息建立。
拓扑排序算法大体思想为:1)遍历有向图各顶点的入度,将所有入度为零的顶点入栈;2)栈非空时,输出一个顶点,并对输出的顶点数计数;3)该顶点的所有邻接点入度减一,若减一后入度为零则入栈;4)重复2)、3),直到栈为空,若输出的顶点数与图的顶点数相等则该图可拓扑排序,否则图中有环;5)重复2)、3)、4)直到序列中所有元素均被遍历,则该序列是拓扑序列,否则不是拓扑序列。
2.2 系统功能模块结构图本程序包括拓扑排序模块和拓扑排序核心算法模块。
3.13.2 数据结构1)图typedef struct stack{int *base;int *top;int stacksize;}sqstack;//栈的结构,存储图的顶点序号typedef struct lnode{int adjvex;struct lnode *next;}ArcNode;//弧结点typedef struct node2{int data;ArcNode *fristarc;}VNode,AdjList[MAX];//顶点数组,fristarc指向与顶点邻接的第一条弧typedef struct{AdjList vertices;int vexnum,arcnum;}Graph;//邻接表图void CreatGraph(Graph &G,int *indegree){cout<<"请输入图的顶点数和边数(且顶点数不能超过"<<MAX<<"个)"<<endl;cin>>G.vexnum>>G.arcnum;cout<<"请输入各个顶点值(整形):"<<endl;for(int i=0;i<G.vexnum;i++)//输入图的顶点{cin>>G.vertices[i].data;G.vertices[i].fristarc=NULL;indegree[i]=0;}for(i=0;i<G.arcnum;i++)//输入图的边{int m,n;ArcNode *p;cout<<"请输入第"<<i+1<<"条边的头结点和尾结点:"<<endl;cin>>m>>n;p=new ArcNode;if(!p)exit(0);indegree[n-1]++;//求每个顶点的入度值p->adjvex=n-1;p->next=G.vertices[m-1].fristarc;G.vertices[m-1].fristarc=p;}}2)栈void Initstack(sqstack &s){s.base=new int;if(!s.base)exit(0);s.top=s.base;s.stacksize= STACK_INIT_SIZE;}void Push(sqstack &s,int &e){*s.top++=e;}int Emptystack(sqstack &s){if(s.base==s.top)return 1;elsereturn 0;}int Pop(sqstack &s,int &e){if(s.base==s.top)return ERROR;e=*--s.top;}3.3 具体实现函数1)程序所需头文件及全局变量#include<iostream>using namespace std;const int MAX=30;const int STACK_INIT_SIZE=100;const int ERROR=0;2)栈的操作①void Initstack(sqstack &s)功能:初始化栈,构造一个空栈S参数:S待初始化的栈②i nt Emptystack(sqstack &s)功能:判断栈是否为空参数:S 待判断的栈返回值:栈为空返回1,栈非空返回0③void Push(sqstack &s,int &e)功能:元素入栈参数:S 待操作的栈:插入元素e为新的栈顶元素④int Pop(sqstack &s,int &e)功能:元素出栈参数:S 待操作的栈:若栈不空,则删除S的栈顶元素,用e返回其值,并返回1,否则返回03)图的建立void CreatGraph(Graph &G,int *indegree)功能:建立有向图,并记录每个节点的入度值参数:G 待建立的图:用indegree记录节点的入度值4)拓扑排序int Toposort(Graph &G,int *indegree)功能:对有向图进行拓扑排序,对排序结果进行顺序和逆序输出参数:G 待排序的图:indegree是节点的入度值5)主函数int main()对各个函数进行调用,实现程序功能判断是否排序成功四、调试分析4.1 数据测试1、对存在环的有向图进行测试有向图的顶点数和边数:4 4各顶点的值:1 2 3 4第一条边1 2第二条边的头结点和尾结点:2 3第三条边的头结点和尾结点:3 4第四条边的头结点和尾结点:4 1测试结果:拓扑排序不成功。
数据结构课程设计环拓扑排序和纸牌游戏 (1)

目录课题一 joseph环 41.1 问题的提出1.1.问题的提出41.2 概要设计2.1算法思想51.3流程图根据算法思想,画程序流程图如下:661.4 源代码1.3.详细设计 7 输入m 、nm>0且n>0的整数建立含n 个结点的链表且用head 指向第一个元素,结点数据域包含password 、No 、以及指向下一结点的指head=>pn ≥2(m%n)==0?n:m%n=>1=>i i<mp →next=>pi++输出p →Nop →password=>m删除p 所指向结点n--输出p →No结束开始1.5 结果与分析.4 测试及性能分析10课题二拓扑排序 112.1 问题的提出2.1 问题的提出112. 2 概要设计112.3 流程图2.根据算法思想,画流程图如下:1212 开始设辅助数组indegree 记录图的各顶点的入度值,并将indegree 数组各变量赋初值。
输入图的顶点数、边数建立一个栈,存储图的顶点的序号用邻接表法建图,并计算出indegree 数组中各变量值根据indegree 数组将入度为0的顶点入栈count 对输出顶点计数0=>count栈不空删除栈顶元素,赋给i count++将与第i 个顶点链接的各顶点入度减1输出第i 个顶点值 顶点入度为0 顶点序号入栈count<G.vexnum输出“拓扑排序成功” 输出“拓扑排序不成功” 结束2.4 源代码132.5 结果与分析2.4 测试及性能分析17课题三纸牌游戏 193.1 问题的提出.1 问题的提出193. 2 概要设计191.当每个号码每次遇到是某个数的倍数时,都会相应的翻一次,这样,每张牌会翻的次数就各不一样,可能很多次,也可能只有一两次,结果就只是要输出在经过各个不同次数的翻牌后,正面向上的牌都有哪几个。
举例说明一下,比如24,第一次它是2的倍数时要从正面翻到背面,当进行到3时,就又要从背面翻回来,而到4时还要在翻,同理呢,到6.8.12…它都要来回的翻。
数据结构课程设计——拓扑排序

. . .. . .课程设计任务书学生:专业班级:指导教师:工作单位:计算机科学系题目: 拓扑排序初始条件:(1)采用邻接表作为有向图的存储结构;(2)给出所有可能的拓扑序列。
(3)测试用例见严蔚敏《数据结构习题集(C语言版)》p48题7.9图要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下容:1. 问题描述简述题目要解决的问题是什么。
2. 设计存储结构设计、主要算法设计(用类C/C++语言或用框图描述)、测试用例设计;3. 调试报告调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。
4. 经验和体会(包括对算法改进的设想)5. 附源程序清单和运行结果。
源程序要加注释。
如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出。
说明:1. 设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。
2. 凡拷贝往年任务书或课程设计充数者,成绩一律无效,以0分记。
时间安排:1.第17周完成,验收时间由指导教师指定2.验收地点:实验中心3.验收容:可执行程序与源代码、课程设计报告书。
指导教师签名:2013年6月14日系主任(或责任教师)签名:年月日拓扑排序目录1问题描述2具体设计2.1存储结构设计2.2主要算法设计2.2.1拓扑排序的算法总体设计2.2.2将有向图表示为邻接表2.2.3拓扑排序函数的设计2.2.4顺序表的运算设计2.3测试用例设计3调试报告3.1设计和编码的分析3.2调试过程问题及解决4经验与体会5用户使用说明6参考文献7附录源代码与运行结果1问题描述题目:拓扑排序如果用有向图表示一个工程,在这种有向图中,用顶点表示活动,用有向边<vi,vj>表示活动vi必须先于活动vj进行,这种有向图叫做顶点表示活动的网络,记作AOV 网络。
对一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得AOV网络中的所有应存在前驱和后继的关系都能得到满足,这种构造AOV网络全部顶点的拓扑有序序列的运算叫做拓扑排序。
第七章--拓扑排序

3 拓扑排序的定义
拓扑排序
拓扑排序就是将AOV网中的所有顶点排列成一个线性序 列,并且满足条件:在AOV网中,如果从顶点vi到顶点vj存在 一条路径,则在该线性序列中,顶点vi一定出现在vj之前。拓 扑排
在有向图中选一个没有前驱(入度为0)的顶点,并且输出之。 从图中删除该顶点和所有以它为尾的弧。
《数据结构》 课程
拓扑排序
主讲教师:李晓娜
目录 CONTENTS
1 问题的导入 2 AOV网的定义 3 拓扑排序的定义 4 拓扑排序的过程
1 问题的导入
例如:我们非常想学习一门计算机 操作系统的课程,但是在修这门 课程之前,我们必须学习一些基 础课,比如程序设计基础、数据 结构、离散数学等等。那么学生 应按怎样的顺序学习这些课程, 才能无矛盾、顺利地完成呢?
课程编号 C1
课程 名称
高等数学
C2
程序设计基础
C3
离散数学
C4
数据结构
C5
算法语言
C6
编译技术
C7
操作系统
C8
普通物理
C9
计算机原理
先修 课程
无
无
C1,C2 C2,C3
C2 C4,C5 C4,C9
C1 C8
1 问题的导入
如何安排学习 计划?
C2
C5
C4 C3
C6
01 AOV网
C1
C8
C7
建立描述课程之间优先关系的有向无环图
重复上述两步,直至全部顶点均已输出;或者当图中不存在无前驱的顶点为止 (此时图中存在环)
V1
V5
拓扑序列:
v0, V1, V2, V3, V4, V5, V6,
数据结构中拓扑排序算法的实现

Ac hi e v e o f To po l o g i c a l Ta x i s Ca l c ul a t i o n i n Da t a St r uc t ur e
LI J i n g
( Gu i z h o u Co mme r c i a l Co U e g e , De p a r t me n t o f Co mp u t e r S c i e n c e a n d T e c h n o l o g y, Gu i y ng a 5 5 0 0 0 4, Ch i n a )
电脑 编程技巧 与维 护 源自数 据结构 中拓 扑排序算 法 的实现
奎 静
( 贵州商业高等专科学校计算机科学与技术系 ,贵阳 5 5 o o o 4 ) 摘 要 :介绍拓扑排序 的算 法,对 于给 出的事件 结点 网络 ,要求依 次求 出入度 ( 或 出度)为 0的顶 点 ,最终得 到一
组拓 扑序 列。通过 对这 一序 列的分析 、比较 ,判 断该 网络 图是否 为循环 图 ,从 而确立 实际应 用的可能性 大小 ,并给 出了计算机 上机 实现 的源程序 。 关键 词 :拓 扑序 列 ; A O E网 ; 数据结构
又如 ,汽车装 配工 程可分解为 以下任 务 :将底盘 放上装配线 ,
装轴 ,将 座位 装在底 盘上 、上 漆 、装 刹车 、装 门等 。任 务之 间具有先后关 系 ,例如在装轴之前必 须先将底板 放上装配线 。
要来 描 述 这 些任 务 的先 后 顺序 就可 用 A O V网 ( A c t i v i t y O n
这些 事件 都可分 为若干个 子事件 ,只要 依次完 成它 们 ,就 可 以最终促 成整个事 件 的完 成 。但这 些子 事件之 间有 时存 在一 定的先决 条件 约束 ,即有 些子事 件必 须在其他 子事 件完 成 以 后方可 开始实施 ;而有些 子事件 则没有 这样 的约束 关 系。例 如 :将早 晨穿 衣的过程看 作是一 项小 工程 。那 必须 先穿 某一 衣物才 能再穿 其他衣物 ( 如先穿 袜子后 穿鞋) ,逐 步完成 工程 的运作 ,也有一些 衣物可以按任意次序穿戴 ( 如袜子 和短裤) 。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
拓扑排序
问题描述:
若用有向网表示教学计划,其中顶点表示某门课程,有向边表示课程之间的先修关系(如果A课程是B课程的先修课程,那么A到B之间有一条有向边从A指向B)。
试设计一个教学计划编制程序,获取一个不冲突的线性的课程教学流程。
(课程线性排列,每门课上课时其先修课程已经被安排)。
基本要求:
(1)输入参数:课程总数,每门课的课程号(固定占3位的字母数字串)和直接先修课的课程号。
(2)若根据输入条件问题无解,则报告适当的信息;否则将教学计划输出到用户指定的文件中。
需求分析:(测试数据加强版)
1、输入形式:
第一行是是个整数t,表示有t组测试数据;
每一组测试数据的第一行是一个整数n,表示结点数目
接下来的n行是n个顶点的信息
接下来的一行是一个整数m,表示有向边的数目
接下来是m行数据每一行是一条有向边的起止结点信息
2、输出形式:
如果可以实现拓扑排序,输出其得到的合法线性序列
否则,输出“Input Error!”;
3、功能描述:
帮助判断当前的课程是否可以安排得当;
如果得当,输出一个合法的修读顺序;
4、样例输入输出:
输入:
2
5
Math
English
Physics
Chinese
Music
5
Math English
Math Physics
English Chinese
Physic Chinese
Chinese Music
5
Math
English
Physics
Chinese
Music
4
Math English
Math Physics
English Chinese
Physic Chinese
输出:
Input Error!
Math English Physics Chinese Music 抽象数据结构类型描述(ADT):
采用邻接表的方式来存储数据:
抽象数据类型描述:
Typedef struct Arc * link;
struct Arc{
Int adjvex;//邻接点编号
Char info[15];//存储结点信息
Link nextarc;//指向下一个邻接点
};
Struct Vex{
Char info; //顶点信息
Int indgree;//顶点的入度
Link firstarc; //指向下一个邻接点
};
概要设计:
算法主题思想:
<1>、在有向图中选择一个没有前驱的顶点,输出之;
<2>、从有向图中删除该顶点和所有以该顶点为尾的边;
<3>、重复上述步骤,直到全部顶点都已经输出了或者图中剩下的顶点
都不满足上述的两个条件位置。
后者说明有向图中存在环。
详细设计:
通过一下函数分块、分步的实现:
void creat() function:建立邻接表
int find(char *str) function:在顶点集中查找信息为str的顶点的编号,
并返回之
void update(int node) function:没输出一个顶点的时候要相应的调用该函
数更新顶点入度信息在main()函数内调用上述函数实现功能描述
C++代码详见:code 10.cpp
#include<iostream>
#include<cstring>
#include<stdlib.h>
using namespace std;
# define Max 1001
int n,m;
typedef struct Arc* link;
struct Arc
{
char info[15];
int adjvex;
link nextarc;
};
struct Vex
{
char info[15];
int indgree;
link firstarc;
}v[Max];
int find(char *str)
{
for(int i=1;i<=n;i++)
if(!strcmp(str,v[i].info))
return i;
}
void creat()
{
cout<<"课程总数:"<<endl;
cin>>n;
cout<<"请输入各个顶点信息(即课程的编号):"<<endl; for(int i=1;i<=n;i++)
{
cin>>v[i].info;
v[i].indgree=0;
v[i].firstarc=NULL;
}
cout<<"请输入有向边数目:";
cin>>m;
cout<<"输入有向边(先修课程编号在前):"<<endl;
for(int i=0;i<m;i++)
{
char ss[15],tt[15];
cin>>ss>>tt;
int s=find(ss),t=find(tt);
v[t].indgree++;
link p=(link)malloc(sizeof(Arc));
strcpy(p->info,v[t].info);
p->adjvex=t;
p->nextarc=v[s].firstarc;
v[s].firstarc=p;
}
}
void update(int node)
{
link p=v[node].firstarc;
while(p)
{
if(v[p->adjvex].indgree>0) v[p->adjvex].indgree--; p=p->nextarc;
}
}
int main()
{
int rel[Max],len=0,t;
cout<<"请输入测试数据数目:"<<endl;
cin>>t;
while(t--)
{
creat();
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
if(!v[i].indgree)
{
rel[len++]=i;
v[i].indgree=-1;
update(i);
}
cout<<"------------------------"<<endl;
if(len<n) cout<<"Input Error!"<<endl; else
{
for(int i=0;i<len;i++)
cout<<v[i].info<<" ";
cout<<endl;
}
cout<<"------------------------"<<endl; }
system("pause");
return 0;
}
/*
2
5
Math
English
Physics
Chinese
Music
5
Math English
Math Physics
English Chinese
Physic Chinese
Chinese Music
5
Math
English
Physics
Chinese
Music
4
Math English
Math Physics
English Chinese
Physic Chinese
*/
调试分析:
调试过程中没有发现什么问题。
测试结果:
用户使用说明:
本程序只支持1000以内的科目数对应的操作。