拓扑排序

拓扑排序
拓扑排序

拓扑排序

摘要

拓扑排序是求解网络问题所需的主要算法。管理技术如计划评审技术和关键路径法都应用这一算法。通常,软件开发、施工过程、生产流程、程序流程等都可作为一个工程。一个工程可分成若干子工程,子工程常称为活动。活动的执行常常伴随着某些先决条件,一些活动必须先于另一活动被完成。利用有向图可以把这种领先关系清楚地表示出来。而有向图的存储可以用邻接表和逆邻接表做存储结构来实现。最后用拓扑排序表示出来就可以了。拓扑排序有两种,一种是无前趋的顶点优先算法,一种是无后继的顶点优先算法,后一种的排序也就是逆拓扑排序。

关键词:拓扑排序;逆拓扑排序;有向图;邻接表;逆邻接表

THE OPERATOR ORDERING PROBLEM IN QUANTUM

HAMITONIAN FOR SOME CONSTRAINT SYSTEMS

ABSTRACT

Topological sort is the main method to solve network problems. Management techniques such as PERT and critical path method is the application of this algorithm. Typically, software development, the construction process, production processes, procedures, processes, etc. can be used as a project. A project can be divided into several sub-projects, often referred to as sub-project activities. The implementation of activities often associated with certain preconditions, some of the activities must be completed before another activity. Use has lead to the relationship of this figure can be expressed clearly. While storage can be used to map the inverse adjacency list and adjacency table to do storage structures. Finally, topological sort that out on it. Topological sort, there are two, one is the predecessor of the vertex without first algorithm, a successor of the vertex is no priority algorithm, the latter sort is the inverse topological sort.

Key words:topological sort; inverse topological; have to figure; adjlink; inverse adjlink

目录

1需求分析 (1)

1.1设计内容 (1)

1.2设计要求 (1)

2概要设计 (1)

2.1邻接表 (1)

2.2逆邻接表 (2)

2.3有向图的拓扑排序........................................................................... (3)

2.4有向图的逆拓扑排序.............. ........ (4)

3详细设计 (4)

3.1 有向图拓扑排序和逆拓扑排序 (4)

3.1 .1 邻接表存储 (4)

3.1.2 逆邻接表存储 (9)

4 调试分析 (11)

4.1 回顾讨论和分析 (11)

4.2 算法复杂度的分析 (11)

4.3 经验和体会 (12)

5用户使用说明 (12)

6 测试数据和测试结果 (12)

参考文献 (15)

附录 (16)

1 需求分析

1.1设计内容

编写函数实现有向图的拓扑排序以及逆拓扑排序,要求有向图用邻接表和逆邻接表作为存储结构分别实现,并比较两者算法时间复杂度。

1.2 设计要求

1.将有向图分别用邻接表与逆邻接表存储

2.实现有向图的拓扑排序和逆拓扑排序

3.比较两种排序的时间复杂度

2 概要设计

图是一种非常有用的数据结构。因为图的结构复杂而使用广泛,所以其存储表示方法也是多种多样,对应于不用的应用问题有不用的表示方法。

2.1 邻接表

邻接表是图的一种链式存储结构。用邻接表法表示图需要保存一个顺序存储的结点表和n个链接存储的边表。结点表的每个表目对应于一个结点,每个表目包括两个字段:一个是结点的数据或指向结点数据的指针,另一个是指向此结点的边表的指针。图的每个结点都有一个边表,一个结点的边表的每个表目对应于与该结点相关联的一条边,每个表目包括两个字段:一个是与此边相关联的另一个结点的序号,另一个是指向边表的下一个表目的指针。

用邻接表法表示有向图,根据需要可以保存每个结点的出边表(即以该结点为始点的边的表),也可以保存每个结点的入边表(即以该结点为终点的边的表)。只保存入边表和出边表之一,则存储n个结点m条边的有向图需要n+m个单元。

在这种存储方法中,对于图中的每一个顶点分别建立一个线性链表。每个链表前

面设置一个头结点,称之为顶点结点。每个顶点结点由两个域组成,如图1-1:

图1-1 邻接表的顶点结点构造

邻接表的第i个链表中的每一个链结点称之为边界点,它表示依附于第i个顶点的一条边,其链结点构造为

图1-2 邻接表的边结点构造

一个图的邻接表存储结构可形式地说明如下:

//------图的邻接表存储表示-----------------

#define MAX_VERTEX_NUM 20

typedef struct ArcNode{

int adjvex; //该弧所指向的顶点的位置

struct ArcNode *nextarc; // 指向下一条弧的指针

InfoType *info; //该弧相关信息的指针

}ArcNode;

typeder struct VNode{

V ertexType data; //顶点信息

ArcNode *firstarc; //指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];

typeder struct{

AdjList vertices;

int vexnum,arcnum; //图的当前顶点数和弧数

int kind; //图的种类标志

}ALGraph;

2.2 逆邻接表

图的逆邻接表反应的是结点的入度邻接情况。也就是说,按照建立邻接表的基本思想,对于有向图中每一个顶点,建立以该顶点为终点(弧头)的一个链表,即把所有以该顶点为终止顶点的边结点链接为一个线性链表。

在有向图中,为图中每个顶点vi建立一个入边表的方法称为逆邻接表的表示法。

入边表中的每个表结点均对应一条以vi为终点(即射入vi)的边。

2.3有向图的拓扑排序

拓扑排序是有向图的一种重要运算。给出有向图G=(V,E),V里结点的线性序列(Vi1,Vi2,……,Vin)称做一个拓扑序列,若此结点序列满足如下条件:若在有向图G中从结点Vi到结点Vj有一条路径,则在序列中结点Vi必在结点Vj之前。

任何无环的有向图,其结点都可以排在一个拓扑序列里,下面给出进行拓扑排序的方法:

(1)从图中选择一个入度为0的结点且输出之。

(2)从图中删掉次结点及其所有的出边。

反复执行这两个步骤,直到所有的结点都输出了,也就是整个拓扑排序完成了,或者直到剩下的图中再也没有入度为0的结点,这就说明此图是有环图,拓扑排序不能再进行下去了。

其抽象算法可以表示为:

TopSort(G){//优先输出无前趋的顶点

while(G中有人度为0的顶点)do{

从G中选择一个人度为0的顶点v且输出之;

从G中删去v及其所有出边;

}

if(输出的顶点数目<|V(G)|)

//若此条件不成立,则表示所有顶点均已输出,排序成功。

Error("G中存在有向环,排序失败!");

}

拓扑排序可以在有向图不同的存储表示上实现。且每个图的拓扑序列并不唯一,即一个图有多个拓扑序列。

若有向图用邻接表法表示,则可以大大提高进行拓扑排序的效率。在结点表里每个结点加进一个in字段,其内容是该结点的入度,这样,不用检查n*n的矩阵,只要检查n个元素的数组就能找出入度为0的结点,进一步我们用入度为0的结点的in字段构造一个链接方式存储的栈,把所有入度为0的结点都推入栈中,于是每次找入度为0的结

点不必检查整个结点表,只要从栈顶取一个结点就行了。对于从栈顶托出的入度为0的结点,检查它的出边表,对每条出边的终点,把它在结点表里对应的表目的in字段值减1,若某个结点的入度减为0了,就把它推到栈里去。用这样的方法进行拓扑排序,初始地建立入度为0的结点的栈检查所有结点一次,排序中每个结点输出一次,每条边被检查一次,执行时间为O(n+m)。

2.4 有向图的逆拓扑排序

无环的有向图的顶点一定在拓扑排序中。与拓扑排序的思想恰好相反,逆拓扑排序是依次输出出度为0的点。

当有向图中无环时,可以利用深度优先遍历进行逆拓扑排序。由于图中无环,从图中的某点出发进行深度优先搜索遍历时,最先推出DFS函数的顶点即是出度为0的顶点,它是拓扑有序序列中的最后一个顶点。由此按推出DFS函数的先后记录下来的顶点序列即为逆向的拓扑序列(逆拓扑序列)。

在对该算法求精时,可用逆邻接表作为G的存储结构。设置一个向量outdegree[0.. 或在逆邻接表的定点表结点中增加1个出度域来保存各顶点当前的出度;设置一个栈或一个队列来暂存所有出度为0的顶点。除了增加一个栈或相邻向量T来保存输出的顶点序列外,该算法完全类似于拓扑排序。

抽象算法描述

算法的抽象描述为:

NonTopSort(G){//优先输出无后继的顶点

while(G中有出度为0的顶点)do {

从G中选一出度为0的顶点v且输出v;

从G中删去v及v的所有人边

}

if(输出的顶点数目<|V(G)|)

Error("G中存在有向环,排序失败!");

}

3 详细设计

逆拓扑排序的结果只需要将所得到的拓扑排序反过来即可。故编程序的重点在于得到有向图的拓扑排序。

3.1有向图的拓扑排序

3.1.1 邻接表存储

分析课题的要求首先则需要一个有向图,因而需要构建一个有向图,其中包括图的各种信息,有弧数,顶点数,有向边的起点与终点。设计程序如下:

void createAlGraph(alGraph &G)//创建有向图

{

int k,j,i;

cout<<"输入顶点数和弧数:";//输入顶点数之后,各顶点从0开始计数

cin>>G.vexnum>>G.arcnum;

for(i=0;i

{

G.vertices[i].data=i;

G.vertices[i].firstarc=NULL;//如果节点的指针为null

}

cout<<"输入弧信息:"<

for(k=1;k<=G.arcnum;k++)

{

cout<<"输入第"<>i>>j;

while(i<0 || i>G.vexnum-1 || j<0 || j>G.vexnum-1)//依次输入各条边的信息

{

cout<<"输入第"<>i>>j;

}

arcNode *p=new arcNode;

arcNode *q=new arcNode;

if(!p)

{

cout<<"Overflow!"<

}

if(!(G.vertices[i].firstarc))

{

G.vertices[i].firstarc=p; // 将弧结点插入到对应的单链表

}

else

{

q=G.vertices[i].firstarc;

while(q->nextarc)

{

q=q->nextarc;

}

q->nextarc=p;

}

p->adjV ex=j; //对弧结点的弧顶点数据域赋值p->nextarc=G.vertices[j].firstarc; //对弧结点下一条弧指针域赋值

}

}

有了图之后,需要将图以邻接表的存储方式存储

typedef struct _arcNode //定义邻接表的节点

{

int adjV ex; //该弧所指向的顶点的位置(邻接点)

_arcNode *nextarc; //指向下一条弧的指针

int info; // 该弧相关信息

}arcNode;

typedef struct _vNode //定义头结点

{

int data; //顶点信息

_arcNode *firstarc; //指向第一条依附该顶点的指针

}vNode;

在表示图的邻接表之前,还要做得重要的一点就是求各个顶点的入度,直到了各个顶点的入度之后才好用邻接表存储,并用邻接表表示出来,其程序如下:

int indegree[MaxVexNum];

void findindegree(alGraph G)//对各顶点求入度{

int i;

arcNode *p;

for(i=0;i

{

indegree[i]=0;

}

for(i=0;i

{

p=G.vertices[i].firstarc;

while(p)

{

indegree[p->adjV ex]++; p=p->nextarc;

}

}

}

最后设计拓扑排序和逆拓扑排序

bool toposort(alGraph G)//求拓扑排序

{

stack s;//建栈

stack r;//建立得到逆拓扑排序的栈

int i,j,k,m;

arcNode *p;

for(i=0;i

{

if(!indegree[i])s.push(i);

}

int count=0;

cout<<"拓扑排序:"<

while(!s.empty())

{

j=s.top(); s.pop();//弹栈

cout<

for(p=G.vertices[j].firstarc;p;p=p->nextarc)

{

k=p->adjV ex; if(!(--indegree[k]))s.push(k);

}

}

cout<

cout<<"逆拓扑排序:"<

while(!r.empty())//逆拓扑排序可以模仿拓扑排序的方法写

{

m= r.top();r.pop();

cout<

}

cout<

if(count

return false;

else

return true;

}

3.1.2逆邻接表存储

逆邻接表的存储与邻接表的存储基本上一致,故只需要在些许地方进行改动,譬如改动了邻接点的判断,程序如下:

void createAlGraph(alGraph &G)//创建有向图

{

int k,j,i;

cout<<"输入顶点数和弧数:";//输入顶点数之后,各顶点从0开始计数

cin>>G.vexnum>>G.arcnum;

for(i=0;i

{

G.vertices[i].data=i;

G.vertices[i].firstarc=NULL;

}

cout<<"输入弧信息:"<

for(k=1;k<=G.arcnum;k++)

{

cout<<"输入第"<>i>>j;

while(i<0 || i>G.vexnum-1 || j<0 || j>G.vexnum-1)

{

cout<<"输入第"<>i>>j;

}

arcNode *p=new arcNode;

arcNode *q=new arcNode;

if(!p)

{

cout<<"Overflow!"<

return;

}

if(!(G.vertices[j].firstarc))

{

G.vertices[j].firstarc=p; // 将弧结点插入到对应的单链表

}

else

{

q=G.vertices[j].firstarc;

while(q->lastarc){

q=q->lastarc;

}

q->lastarc=p;

}

p->adjV ex=i; //对弧结点的弧顶点数据域赋值p->lastarc=G.vertices[i].firstarc; //对弧结点下一条弧指针域赋值

}

}

将此程序改动之后则需要注意此时得到的拓扑排序和逆拓扑排序的结果刚好相反,故将得到的顺序颠倒即可。

主函数

int main()//主函数

{

alGraph G;

cout<<"创建一个有向图:"<

createAlGraph(G);//调用此方法创建了一个有向图

cout<

printAlGraph(G);//调用此方法得出图的邻接表

cout<

findindegree(G);//求出各定点的入度

cout<

if(toposort(G))

{

cout<<"排序成功!"<

}

else //否则退出

{

cout<<"退出."<

}

}

4 调试分析

4.1 回顾讨论和分析

对于程序的设计,我觉得首先要弄懂题目的要求,解读题目然后将程序分开成几个部分处理。其中包括:有向图的构建,邻接表的存储结构,拓扑排序,主函数。

其实分别处理了之后,发现无法实现,有向图无法与邻接表联系起来,则需要求各个定点的入度,然后用邻接表表示出来,这样设计了findindegree(G)方法。这样之后能够实现拓扑排序。

调试的过程中还会出现指针越界的情况,则程序将不能运行。另外注意在想要使用一个变量或定义的时候必须提前定义,不然会报错,例如:error C2065: 'i' : undeclared identifier。还要注意中英文的换写,不符合格式的时候也会报错。

接下来要解决逆拓扑排序,想到拓扑排序中运用到的是栈S,而逆拓扑排序就是将拓扑序列倒过来,这也就可以让栈S中的元素再次出栈就可以。这时就再设一个空栈R,让栈S中的元素出栈并且进到栈R中,这样就得到了一个相反的序列,从而解决了逆拓扑排序的问题。

而相应的逆邻接表存储有向图后实现拓扑排序和逆拓扑的程序就相对之间较好解决了。首先思想是一样的,将程序中的邻接表换成逆邻接表就可以了。且逆邻接表存储有向图的时候发现,对于创建的有向图中不能有环,如果有环,则无法执行,故程序中仍有缺陷。

4.2 算法复杂度的分析

1.拓扑排序

总是选择入度为0的结点输出并删除该顶点的所有边。设置各个顶点入度时间是O(n+e),设置栈或队列的时间是O(n),算法时间复杂度为O(n+e)。

2.逆拓扑排序

总是选择出度为0的结点输出并删除该顶点的所有边。设置各个顶点出度时间是O(n+e),设置栈或队列的时间是O(n),算法时间复杂度为O(n+e)。求得的是逆拓扑序列。

4.3 经验和体会

在此次程序设计中我学到了很多,也懂得了只有自己动手做才能够真正将知识弄懂,而数据结构的程序也只有自己写了之后才能够明白其中的道理。其中的每一步都是我们自己的进步,不管是去图书馆借阅图书,还是上网自己搜,都能有所收获的。

在程序设计的过程中,应该弄懂程序中每句语句的含义和作用,且要学会反思和以一举三,这样才能够收获的更多

而在程序设计方面,我们应该注意添加注释,我想这是一个优秀程序员所必须具备的品质。只有添加注释才能让别人更快的看懂你的程序,而且如果以后有什么需要修改的地方也能更好的修改。对于不同的分块也可以更好的分析。另外在设计操作的时候还要通俗易懂,让使用者能够一看就懂,知道自己怎样才运行程序,这样程序才能被更多的人接受。另外也注意排版,让自己的程序更加的美观。

5 用户使用说明

1.邻接表存储时将程序运行,并且按照提示进行操作的步骤结果如下:

A 将程序代码运用于Microsoft Visual C++的环境,保存并运行则会出现灰框,接下来按

提示操作

B 输入你想构造的有向图的顶点数目和边的条数,中间用空格间隔。另外在此说明输入

顶点的数目之后,顶点就从0开始依次排序。按enter键进行下一步操作

C 输入每条边的起点和终点,中间用空格间隔。输入的信息量条数要与你之前输入的边

的条数相吻合。按enter键进行就可以得到想要的结果,即拓扑排序和逆拓扑排序。

2.逆邻接表存储时的操作步骤与邻接表存储时相类似,故操作步骤省略。但注意此时得

到拓扑排序和逆拓扑排序的顺序相反。

6 测试数据和测试结果

有向图用邻接表存储实现拓扑排序和逆拓扑排序:

输入的数据为4 2.

输入的数据为:1 2

0 2

从图中可以看到有向图的邻接表,并且其拓扑排序:3 1 0 2,逆拓扑排序为:2 0 1 3.

有向图用逆邻接表存储实现拓扑排序和逆拓扑排序(此处演示一个简单有向图的执行):

此时输入的数据为:4 3.按enter键后的结果为:

接着按提示要求输入:0 3(enter),2 3(enter),1 3(enter),执行后结构为:

得到了有效的结果,则此次执行成功。

参考文献

[1]李云清,杨庆红,揭安全.数据结构(C 语言版).北京:人民邮电出版社,2004.6:162-168,186-189.

[2]严蔚敏,吴伟民.数据结构(C 语言版).北京:清华大学出版社,2007:160-163,

179-183.

[3]王翠茹,袁和金,刘军,马玉梅,牛为华.数据结构(C 语言版).北京:中国国

力出版社,2006.9:143-148.

[4]唐发根.数据结构教程(第二版).北京:北京航空航天大学出版社,2005.5:263-264.

[5]叶核亚.数据结构(C++版).北京:机械工业出版社,2004.8:220-222

[6]张晓莉,刘振鹏,许百成.数据结构与算法.北京:机械工业出版社,2002.10:168-172.

附录源程序清单源程序1:邻接表存储有向图实现拓扑排序和逆拓扑排序

#include

#include

#include

#define MaxV exNum 1000

Ss

using namespace std;

int indegree[MaxVexNum];

typedef struct _arcNode //定义邻接表

{

int adjV ex; //该弧所指向的顶点的位置(邻接点)

_arcNode *nextarc; //指向下一条弧的指针

int info; // 该弧相关信息

}arcNode;

typedef struct _vNode //定义头结点

{

int data; //顶点信息

_arcNode *firstarc; //指向第一条依附该顶点的指针

}vNode;

typedef struct _alGraph

{

_vNode vertices[MaxV exNum];//顶点的集合,最大的顶点数

int vexnum,arcnum; //图的当前顶点数和弧数

}alGraph;

void createAlGraph(alGraph &G)//创建有向图

{

int k,j,i;

cout<<"输入顶点数和弧数:";//输入顶点数之后,各顶点从0开始计数

cin>>G.vexnum>>G.arcnum;

for(i=0;i

{

G.vertices[i].data=i;

G.vertices[i].firstarc=NULL;

}

cout<<"输入弧信息:"<

for(k=1;k<=G.arcnum;k++)

{

cout<<"输入第"<>i>>j;

while(i<0 || i>G.vexnum-1 || j<0 || j>G.vexnum-1)

{

cout<<"输入第"<

尾:"; cin>>i>>j; //若不符合则重新输入}

arcNode *p=new arcNode;

arcNode *q=new arcNode;

if(!p)

{

cout<<"Overflow!"<

return;

}

if(!(G.vertices[i].firstarc))

{

G.vertices[i].firstarc=p;

// 将弧结点插入到对应的单链表

}

else

{

q=G.vertices[i].firstarc;

while(q->nextarc)

{

q=q->nextarc;

}

q->nextarc=p;

}

p->adjV ex=j;

//对弧结点的弧顶点数据域赋值

p->nextarc=G.vertices[j].firstarc; //对弧结点下一条弧指针域赋值

}

} void printAlGraph(alGraph G)//设计有向图{

int i;

char a=47,b=92;//“b”表示“/”

arcNode *p;

cout<<"该有向图的逆邻接表如下:"<

for(i=0;i

{

cout<<"["< ";

if(!(G.vertices[i].firstarc))

{

cout<<" "<

}

else

{

for(p=G.vertices[i].firstarc;p;p=p->nextarc) {

cout<adjV ex<<" -> ";

}

cout<

}

}

}

void findindegree(alGraph G)//对各顶点求入度

{

int i;

arcNode *p;

数据结构拓扑排序课程设计

课题二拓扑排序 2.1 问题的提出2.1 问题的提出 任务:编写函数实现图的拓扑排序。 程序所实现的功能:建立对应的邻接表,对该图进行拓扑排序,并显示排序 结果。 输入: 顶点数, 边数及各顶点信息(数据格式为整形) 输出: 拓扑排序结果。 2. 2 概要设计 1.拓扑排序是指由某个集合上的一个偏序得到该集合上的一个全序。更直观地讲,一个偏序是自反的、反对称的,用图表示时每个点都有环且只有单向边。拓扑排序的任务是在这个偏序上得到一个全序,即得到一个完成整个项目的各步骤的序列。 2.解决拓扑排序的方法如下: (1)在有向图中选一个没有前驱的顶点且输出之。 (2)从图中删除该顶点和所有以它为尾的弧。 重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后一种情况则说明有向图中存在环。具体的算法实现参照源程序。 3.构造邻接表图:typedef struct{ AdjList vertices; int vexnum,arcnum; }Graph;//邻接表图 4.为了避免重复检测入度为零的顶点,源程序中设了一个栈,暂存所有入度为零的顶点:typedef struct stack{ int *base; int *top; int stacksize;

}sqstack;//栈的结构,存储图的顶点序号 2.3 流程图2.根据算法思想,画流程图如下:

2.4 源代码 //采用尾插法创的邻接图 #include using namespace std; const int MAX=20; const int STACK_INIT_SIZE=100; const int ERROR=0; typedef struct stack{ int *base; int *top; int stacksize; }sqstack;//栈的结构,存储图的顶点序号 typedef struct lnode { int adjvex; struct lnode *next; }ArcNode;//弧结点 typedef struct node2 { char data; ArcNode *fristarc; }VNode,AdjList[MAX];//顶点数组,fristarc指向与顶点邻接的第一条弧 typedef struct{ AdjList vertices; int vexnum,arcnum; }Graph;//邻接表图 void Initstack(sqstack &s) { s.base=new int;

拓扑排序

拓扑排序 摘要 拓扑排序是求解网络问题所需的主要算法。管理技术如计划评审技术和关键路径法都应用这一算法。通常,软件开发、施工过程、生产流程、程序流程等都可作为一个工程。一个工程可分成若干子工程,子工程常称为活动。活动的执行常常伴随着某些先决条件,一些活动必须先于另一活动被完成。利用有向图可以把这种领先关系清楚地表示出来。而有向图的存储可以用邻接表和逆邻接表做存储结构来实现。最后用拓扑排序表示出来就可以了。拓扑排序有两种,一种是无前趋的顶点优先算法,一种是无后继的顶点优先算法,后一种的排序也就是逆拓扑排序。 关键词:拓扑排序;逆拓扑排序;有向图;邻接表;逆邻接表

THE OPERATOR ORDERING PROBLEM IN QUANTUM HAMITONIAN FOR SOME CONSTRAINT SYSTEMS ABSTRACT Topological sort is the main method to solve network problems. Management techniques such as PERT and critical path method is the application of this algorithm. Typically, software development, the construction process, production processes, procedures, processes, etc. can be used as a project. A project can be divided into several sub-projects, often referred to as sub-project activities. The implementation of activities often associated with certain preconditions, some of the activities must be completed before another activity. Use has lead to the relationship of this figure can be expressed clearly. While storage can be used to map the inverse adjacency list and adjacency table to do storage structures. Finally, topological sort that out on it. Topological sort, there are two, one is the predecessor of the vertex without first algorithm, a successor of the vertex is no priority algorithm, the latter sort is the inverse topological sort. Key words:topological sort; inverse topological; have to figure; adjlink; inverse adjlink

拓扑排序-数据结构实验

拓扑排序 问题描述: 若用有向网表示教学计划,其中顶点表示某门课程,有向边表示课程之间的先修关系(如果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): 采用邻接表的方式来存储数据: 抽象数据类型描述:

数据结构拓扑排序实验报告

拓扑排序 [基本要求] 用邻接表建立一个有向图的存储结构。利用拓扑排序算法输出该图的拓扑排序序列。 [编程思路] 首先图的创建,采用邻接表建立,逆向插入到单链表中,特别注意有向是不需要对称插入结点,且要把输入的字符在顶点数组中定位(LocateVex(Graph G,char *name),以便后来的遍历操作,几乎和图的创建一样,图的顶点定义时加入int indegree,关键在于indegree 的计算,而最好的就是在创建的时候就算出入度,(没有采用书上的indegree【】数组的方法,那样会增加一个indegree算法,而是在创建的时候假如一句计数的代码(G.vertices[j].indegree)++;)最后调用拓扑排序的算法,得出拓扑序列。 [程序代码] 头文件: #define MAX_VERTEX_NUM 30 #define STACKSIZE 30 #define STACKINCREMENT 10 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define TRUE 1 #define FALSE 0 typedef int Status; typedef int InfoType; typedef int Status; typedef int SElemType; /* 定义弧的结构*/ typedef struct ArcNode{ int adjvex; /*该边所指向的顶点的位置*/ struct ArcNode *nextarc; /*指向下一条边的指针*/ InfoType info; /*该弧相关信息的指针*/

拓扑排序课程设计报告

沈阳航空航天大学 课程设计报告 课程设计名称:数据结构课程设计 课程设计题目:拓扑排序算法 院(系):计算机学院 专业:计算机科学与技术(嵌入式系统方向) 班级:14010105班 学号:2011040101221 姓名:王芃然 指导教师:丁一军

目录 1 课程设计介绍 (1) 1.1课程设计内容 (1) 1.2课程设计要求 (1) 2 课程设计原理 (2) 2.1课设题目粗略分析 (2) 2.2原理图介绍 (2) 2.2.1 功能模块图 (2) 2.2.2 流程图分析 (3) 3 数据结构分析 (7) 3.1存储结构 (7) 3.2算法描述 (7) 4 调试与分析 (12) 4.1调试过程 (12) 4.2程序执行过程 (12) 参考文献 (14) 附录(关键部分程序清单) (15)

1 课程设计介绍 1.1 课程设计内容 由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。若在图一的有向图上人为的加一个表示V2<=V3的弧(“<=”表示V2领先于V3)则图一表示的亦为全序且这个全序称为拓扑有序,而由偏序定义得到拓扑有序的操作便是拓扑排序。在AOV网中为了更好地完成工程,必须满足活动之间先后关系,需要将各活动排一个先后次序即为拓扑排序。编写算法建立有向无环图,主要功能如下: 1.能够求解该有向无环图的拓扑排序并输出出来; 2.拓扑排序应该能处理出现环的情况; 3.顶点信息要有几种情况可以选择。 1.2 课程设计要求 1.输出拓扑排序数据外,还要输出邻接表数据; 2.参考相应的资料,独立完成课程设计任务; 3.交规范课程设计报告和软件代码。

有向图拓扑排序算法的实现

数据结构课程设计 设计说明书 有向图拓扑排序算法的实现 学生姓名 学号 班级 成绩 指导教师魏佳 计算机科学与技术系 2010年2月22日

数据结构课程设计评阅书 注:指导教师成绩60%,答辩成绩40%,总成绩合成后按五级制记入。

课程设计任务书 2010—2011学年第二学期 专业:信息管理与信息系统学号:姓名: 课程设计名称:数据结构课程设计 设计题目:有向图拓扑排序算法的实现 完成期限:自2011 年 2 月22 日至2011 年 3 月 4 日共 2 周 设计内容: 用C/C++编写一个程序实现有向图的建立和排序。要求建立有向图的存储结构,从键盘输入一个有向图,程序能够自动进行拓扑排序。 设计要求: 1)问题分析和任务定义:根据设计题目的要求,充分地分析和理解问题,明确问题要求做什么?(而不是怎么做?)限制条件是什么?确定问题的输入数据集合。 2)逻辑设计:对问题描述中涉及的操作对象定义相应的数据类型,并按照以数据结构为中心的原则划分模块,定义主程序模块和各抽象数据类型。逻辑设计的结果应写出每个抽象数据类型的定义(包括数据结构的描述和每个基本操作的功能说明),各个主要模块的算法,并画出模块之间的调用关系图; 3)详细设计:定义相应的存储结构并写出各函数的伪码算法。在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基本操作的规格说明尽可能明确具体。详细设计的结果是对数据结构和基本操作做出进一步的求精,写出数据存储结构的类型定义,写出函数形式的算法框架; 4)程序编码:把详细设计的结果进一步求精为程序设计语言程序。同时加入一些注解和断言,使程序中逻辑概念清楚; 5)程序调试与测试:采用自底向上,分模块进行,即先调试低层函数。能够熟练掌握调试工具的各种功能,设计测试数据确定疑点,通过修改程序来证实它或绕过它。调试正确后,认真整理源程序及其注释,形成格式和风格良好的源程序清单和结果; 6)结果分析:程序运行结果包括正确的输入及其输出结果和含有错误的输入及其输出结果。算法的时间、空间复杂性分析; 7)编写课程设计报告; 以上要求中前三个阶段的任务完成后,先将设计说明数的草稿交指导老师面审,审查合格后方可进入后续阶段的工作。设计工作结束后,经指导老师验收合格后将设计说明书打印装订,并进行答辩。 指导教师(签字):教研室主任(签字): 批准日期:2011年2月21 日

图的最短路径、拓扑排序和关键路径

数据结构课程辅导 ---图的最短路径、拓扑排序和关键路径 一、最短路径 由图的概念可知,在一个图中,若从一顶点到另一顶点存在着一条路径(这里只讨论无回路的简单路径),则称该路径长度为该路径上所经过的边的数目,它也等于该路径上的顶点数减1。由于从一顶点到另一顶点可能存在着多条路径,每条路径上所经过的边数可能不同,即路径长度不同,我们把路径长度最短(即经过的边数最少)的那条路径叫做最短路径,其路径长度叫做最短路径长度或最短距离。 上面所述的图的最短路径问题只是对无权图而言的,若图是带权图,则把从一个顶点i到图中其余任一个顶点j的一条路径上所经过边的权值之和定义为该路径的带权路径长度,从vi到vj可能不止一条路径,我们把 带权路径长度最短(即其值最小)的那条路径也称作最短路径,其权值也称作最短路径长度或最短距离。 例如,在图3-1中,从v0到v4共有三条路径:{0,4},{0,1,3,4}和 {0,1,2,4},其带权路径长度分别为30,23和38,可知最短路径为{0,1,3,4},最短距离为23。 图3-1 带权图和对应的邻接矩阵 实际上,这两类最短路径问题可合并为一类,这只要把无权图上的每条边标上数值为1的权就归属于有权图了,所以在以后的讨论中,若不特别指明,均认为是求带权图的最短路径问题。 求图的最短路径问题用途很广。例如,若用一个图表示城市之间的运输网,图的顶点代表城市,图上的边表示两端点对应城市之间存在着运输线,边上的权表示该运输线上的运输时间或单位重量的运费,考虑到两城市间的海拔高度不同,流水方向不同等因素,将造成来回运输时间或运费的不同,所以这种图通常是一个

拓扑排序课程设计报告

拓扑排序 一问题描述 本次课程设计题目是:编写函数实现图的拓扑排序 二概要设计 1.算法中用到的所有各种数据类型的定义 在该程序中用邻接表作为图的存储结构。首先,定义表结点和头结点的结构类型,然后定义图的结构类型。创建图用邻接表存储的函数,其中根据要求输入图的顶点和边数,并根据要求设定每条边的起始位置,构建邻接表依次将顶点插入到邻接表中。 拓扑排序的函数在该函数中首先要对各顶点求入度,其中要用到求入度的函数,为了避免重复检测入度为零的顶点,设置一个辅助栈,因此要定义顺序栈类型,以及栈的函数:入栈,出栈,判断栈是否为空。 2.各程序模块之间的层次调用关系 第一部分,void CreatGraph(ALGraph *G)函数构建图,用邻接表存储。这个函数没有调用函数。 第二部分,void TopologicalSort(ALGraph *G)输出拓扑排序函数,这个函数首先调用FindInDegree(G,indegree)对各顶点求入度indegree[0……vernum-1];然后设置了一个辅助栈,调用InitStack(&S)初始化栈,在调用Push(&S,i)入度为0者进栈,while(!StackEmpty(&S))栈不为空时,调用Pop(&sS,&n)输出栈中顶点并将以该顶点为起点的边删除,入度indegree[k]--,当输出某一入度为0的顶点时,便将它从栈中删除。 第三部分,主函数,先后调用void CreatGraph(ALGraph *G)函数构建图、void TopologicalSort(ALGraph *G)函数输出拓扑排序实现整个程序。 3.设计的主程序流程

拓扑排序算法

图的拓扑排序操作 一、实验内容 题目:实现下图的拓扑排序。 5 二、目的与要求 (一)目的 1、了解拓扑排序的方法及其在工程建设中的实际意义。 2、掌握拓扑排序的算法,了解拓扑排序的有向图的数据结构。 (二)要求 用C语言编写程序,实现图的拓扑排序操作。 三、设计思想 首先对有向图,我们采取邻接表作为数据结构。且将表头指针改为头结点,其数据域存放该结点的入度,入度设为零的结点即没有前趋。 在建立邻接表输入之前,表头向量的每个结点的初始状态为数据域VEX(入度)为零,指针域NXET为空,每输入一条弧< J, K > 建立链表的一个结点,同时令k 的入度加1,因此在输入结束时,表头的两个域分别表示顶点的入度和指向链表的第一个结点指针。 在拓扑排序的过程之中,输入入度为零(即没有前趋)的顶点,同时将该顶点的直接后继的入度减1。 (1)、查邻接表中入度为零的顶点,并进栈。 (2)、当栈为空时,进行拓扑排序。 (a)、退栈,输出栈顶元素V。 (b)、在邻接表中查找Vj的直接后继Vk,将Vk的入度减一,并令入度减至零的顶点进栈。 (3)、若栈空时输出的顶点数不是N个则说明有向回路,否则拓扑排序结束。为建立存放入度为零的顶点的栈,不需要另分配存储单元,即可借入入度为零的数据域。一方面,入度为零的顶点序号即为表头结点的序号,另一方面,借用入度为零的数据域存放带链栈的指针域(下一个入度的顶点号)。

四、具体算法设计 #include #include #include #include #include using namespace std; #define MAX 9999 stackmystack; int indegree[MAX]; struct node { int adjvex; node* next; }adj[MAX]; int Create(node adj[],int n,int m)//邻接表建表函数,n代表定点数,m代表边数{ int i; node *p; for(i=0;i<=n-1;i++) { adj[i].adjvex=i; adj[i].next=NULL; } for(i=0;i<=m-1;i++) { cout<<"请输入第"<>u>>v; p=new node; p->adjvex=v; p->next=adj[u].next; adj[u].next=p; } return 1; } void print(int n)//邻接表打印函数 { int i; node *p; for(i=0;i<=n-1;i++) { p=&adj[i]; while(p!=NULL) { cout<adjvex<<' '; p=p->next; } cout<

拓扑排序(算法与数据结构课程设计)

拓扑排序 一、问题描述 在AOV网中为了更好地完成工程,必须满足活动之间先后关系,需要将各活动排一个先后次序即为拓扑排序。拓扑排序可以应用于教学计划的安排,根据课程之间的依赖关系,制定课程安排计划。按照用户输入的课程数,课程间的先后关系数目以及课程间两两间的先后关系,程序执行后会给出符合拓扑排序的课程安排计划。 二、基本要求 1、选择合适的存储结构,建立有向无环图,并输出该图; 2、实现拓扑排序算法; 3、运用拓扑排序实现对教学计划安排的检验。 三、算法思想 1、采用邻接表存储结构实现有向图;有向图需通过顶点数、弧数、顶点以及弧等信息建立。 2、拓扑排序算法void TopologicalSort(ALGraph G) 中,先输出入度为零的顶点,而后输出新的入度为零的顶点,此操作可利用栈或队列实现。考虑到教学计划安排的实际情况,一般先学基础课(入度为零),再学专业课(入度不为零),与队列先进先出的特点相符,故采用队列实现。 3、拓扑排序算法void TopologicalSort(ALGraph G),大体思想为: 1)遍历有向图各顶点的入度,将所有入度为零的顶点入队列; 2)队列非空时,输出一个顶点,并对输出的顶点数计数; 3)该顶点的所有邻接点入度减一,若减一后入度为零则入队列; 4)重复2)、3),直到队列为空,若输出的顶点数与图的顶点数相等则该图可拓扑排序,否则图中有环。 4、要对教学计划安排进行检验,因此编写了检测用户输入的课程序列是否是拓扑序列的算法void TopSortCheck(ALGraph G),大体思想为: 1)用户输入待检测的课程序列,将其存入数组; 2)检查课程序列下一个元素是否是图中的顶点(课程),是则执行3),否则输出“课程XX不存在”并跳出; 3)判断该顶点的入度是否为零,是则执行4),否则输出“入度不为零”并跳出; 4)该顶点的所有邻接点入度减一; 5)重复2)、3)、4)直到课程序列中所有元素均被遍历,则该序列是拓扑序列,否则不是拓扑序列。

C++实现图的拓扑排序

#include #include #include usingnamespace std; constint MAX=100; struct ArcNode { int adjVNode; //节点编号 ArcNode *nextArcNode; // 指向邻接到同一节点的其他节点 ArcNode(){nextArcNode=NULL;} }; struct VNode { int num; //节点编号 ArcNode *firstArcNode; //指向该节点邻接的节点 VNode(){firstArcNode=NULL;} }; struct Graph { int vexnum; //图点数 int arcnum; //图边数 VNode vertices[MAX]; //图的邻接表,指针数组 }; bool topSort(Graph G, int *indegree,int *TopNum) { int count=0; stack Q; for(int i=0;inextArcNode)

{ indegree[p->adjVNode]--; if(indegree[p->adjVNode]==0) Q.push(p->adjVNode); } } if(count!=G.vexnum) returnfalse; returntrue; } int main() { Graph G; ifstream fin("in.txt"); cout<<"输入节点数和边数: "; cin >> G.vexnum >> G.arcnum; //G.vertices=new VNode[G.vexnum]; for(int i=0;i> u >> v; cin >> u >> v; p=new ArcNode(); p->adjVNode=v-1; p->nextArcNode=G.vertices[u-1].firstArcNode; G.vertices[u-1].firstArcNode=p; indegree[v-1]++; //cout << endl; } int *TopNum=newint[G.vexnum]; if(topSort(G,indegree,TopNum)) {

拓扑排序

目录 一、系统开发的背景 (1) (一)问题描述 (1) (二)任务要求 (1) (三)测试数据 (2) (四)系统模块结构设计 (2) 三、系统的设计与实现 (3) (一)系统流程图: (3) (二)主函数模块 (4) (三)图存储结构的建立 (4) 四、系统测试 (8) (一)测试界面选择的实现 (8) (二)测试拓扑排序的实现 (8) (三)测试关键活动的实现 (8) 五、总结 (9)

六、附件(代码、部分图表) (10)

拓扑排序 一、系统开发的背景 为了在科技不断进步的今天能够紧跟着时代的步伐,人们开始不断地追求方便和快捷的生活方式,在这个新鲜的时代,越来越多的新鲜事物层出不穷,为人们提供着各种方便和便利,为了更好地适应和接受这个时刻进步着的社会,我们要努力赶上。在实际工作中,经常要使用一个有向图来表示工程的施工流程或者产品生产的流程图。也就是说,一个大的工程经常被划分为若干个较小的子工程,这些子工程称为“活动”(Activity)。当这些子工程全部完成时,整个工程也就完成了。并且更要关心整个工程完成的最短时间,这就是有向权图的另一个重要应用——工程进度的关键路径问题。用图的邻接表(出边表)表示方法,实现拓扑排序和关键路径的求解过程。 二、系统分析与设计 (一)问题描述 拓扑排序可判断AOV网络中是否存在回路,使得所有活动可排成一个线性序列,使用每个活动的所有前驱活动都排在该活动的前面。 关键路径的工期决定了整个项目的工期。任何关键路径上的终端元素的延迟将直接影响项目的预期完成时间(例如在关键路径上没有浮动时间)。 (二)任务要求 构建AOV网络,并输出其拓扑序列结果,输出该图的关键路径和关键活动,存储结构自行选择。

数据结构-拓扑排序

14信计2015-2016(一) 数据结构课程设计 设计题目拓扑排序 设计时间2016.1.11——2016.1.15 学生姓名冯佳君 学生学号20140401105 所在班级14信计1 指导教师刘风华 徐州工程学院数学与物理科学学院 一、需求分析

1.问题描述 本次课程设计题目是:用邻接表构造图然后进行拓扑排序,输出拓扑排序序列。 拓扑排序的基本思想为: 1)从有向图中选一个无前驱的顶点输出; 2)将此顶点和以它为起点的弧删除; 3) 重复1)、 2)直到不存在无前驱的顶点; 4) 若此时输出的顶点数小于有向图中的顶点数,则说明有向图中存在回路,否则输出的顶点的顺序即为一个拓扑序列。 2.拓扑排序有向图拓朴排序算法的基本步骤如下: 1)从图中选择一个入度为0的顶点,输出该顶点; 2)从图中删除该顶点及其相关联的弧,调整被删弧的弧头结点的入度(入度-1); 3)重复执行1)、2)直到所有顶点均被输出,拓朴排序完成或者图中再也没有入度为0的顶点(此种情况说明原有向图含有环)。 3.基本要求 (1)输入的形式和输入值的范围; 首先是输入要排序的顶点数和弧数,都为整型,中间用分隔符隔开;再输入各顶点的值,为正型,中间用分隔符隔开;然后输入各条弧的两个顶点值,先输入弧头,再输入弧尾,中间用分隔符隔开,输入的值只能是开始输入的顶点值否则系统会提示输入的值的顶点值不正确,请重新输入,只要继续输入正确的值就行。 (2)输出的形式; 首先输出建立的邻接表,然后是最终各顶点的出度数,再是拓扑排序的序列,并且每输出一个顶点,就会输出一次各顶点的入度数。 (3) 程序所能达到的功能; 因为该程序是求拓扑排序,所以算法的功能就是要输出拓扑排序的序列,在一个有向图中,若用顶点表示活动,有向边就表示活动间先后顺序,那么输出的拓扑序列就表示各顶点间的关系为反映出各点的存储结构,以邻接表存储并输出各顶点的入度。 二、概要设计

【数据结构算法】实验9 图的拓扑排序问题(附源代码)

浙江大学城市学院实验报告 课程名称数据结构与算法 实验项目名称实验九图的拓扑排序问题 实验成绩指导老师(签名)日期 一.实验目的和要求 1.掌握拓扑排序概念。 2.理解并能实现拓扑排序算法(采用邻接表表示图)。 二. 实验内容 1、编写用邻接表表示有向无权图时图的基本操作的实现函数,具体包括: ①初始化用邻接表表示的有向无权图void InitAdjoin(adjlist G); ②建立用邻接表表示的有向无权图void CreateAdjoin (adjlist G, int n) (即 通过输入图的每条边建立图的邻接表); ③输出用邻接表表示的有向无权图void PrintAdjoin (adjlist G, int n) (即输 出图的每条边)。 把邻接表的结构定义及这些基本操作实现函数存放在头文件Graph3.h中。 2、编写拓扑排序算法void Toposort( adjlist G, int n) (输入为图的邻接 表,输出为相应的拓扑序列)。 3、编写测试程序(即主函数),首先建立并输出有向无权图,然后进行拓 扑排序。 要求:把拓扑排序函数Toposort以及主函数存放在主文件test9_3.cpp中。 测试数据如下: 4、填写实验报告,实验报告文件取名为report9.doc。 5、上传实验报告文件report9.doc与源程序文件test9_3.cpp及Graph3.h 到Ftp服务器上自己的文件夹下。

三. 函数的功能说明及算法思路 包括每个函数的功能说明,及一些重要函数的算法实现思路 【结构说明】 const int MaxVertexNum =10; //图的最大顶点数 const int MaxEdgeNum =100; //边数的最大值 struct EdgeNode{ //链表边结点,表示弧 int adjvex; //存放与头结点顶点有关的另一个顶点在邻接表(数组)中的下标。 EdgeNode *next; //指向链表下一个结点 }; typedef struct VNode{ //邻接表,表示顶点 int data; // 顶点数据,顶点名称 EdgeNode *firstarc; // 指向边结点链表第一个结点 } adjlist[MaxVertexNum]; 【函数说明】 ①void InitAdjoin(adjlist G) 功能:初始化用邻接表表示的有向无权图 思路:将邻接表的所有顶点置为-1,边结点链表指针置为NULL ②void CreateAdjoin (adjlist &G, int n) 功能:建立用邻接表表示的有向无权图(即通过输入图的每条边建立图的邻接表)思路:按照输入的顶点信息,新建边结点链入邻接表中对应位置 ③void PrintAdjoin (adjlist G, int n) 功能:输出用邻接表表示的有向无权图(即输出图的每条边) 思路:按照一定的格式输出邻接表 ④void Toposort( adjlist G, int n) 功能:输入图的邻接表,输出相应的拓扑序列 思路:初始化数组d[ ],利用数组的空间建立入度为零的顶点栈并设置栈顶指针。当入度为零的顶点栈不空时,重复执行以下步骤:从顶点栈中退出一个顶点, 并输出之;将该顶点的出边邻接点入度减一,如果出边邻接点入度减至0,则该顶点入栈,更新栈顶指针。完成整个循环后,判断输出的顶点个数是否少于邻接表的顶点个数,如果少于则说明存在回路,打印输出信息。 四. 实验结果与分析 包括运行结果截图等 【测试数据】

拓扑排序算法计算代码依赖关系

我们平常所使用的主流编译器,都具有多源代码文件支持.例如把一些类定义在相应的文件中,要使用到这些类时,需要包含定义这个类的文件(如C++),或引用类所在的名字空间(如JAVA),或将这个文件作为单元引用(如Object Pascal) 当我们自己要实现一个支持多源代码文件的编译器时,需要在编译某个源代码文件之前,先编译这个源代码所引用到的文件.例如有一个源文件a.src,里面定义了一个类,内容如下: class List { public void Add(Object obj) { ... } } 然后有一个源文件b.src,里面用到了List类,内容如下: using "a.src" class Test { public static main(String argv[]) { List objs = new List; List.Add(10, 20); //有语法错误 } } 在编译b.src时,如果a.src文件未被预先编译,编译器将无法识别List类,也无法判断List类是否具有成员函数Add,以及对Add的调用参数列表是否正确等.这时就需要先分析b.src引用了哪些文件,这些文件又引用到了其它哪些文件,并优先编译处于引用列表顶端的文件,并以此类推. 例如存在下面几个源代码文件A, B, C, D, E. 引用关系如下: A引用: B, C B引用: D, E C引用: B, E D引用: E E没引用其它文件,这里需要的编译顺序应该如下: E D B C A 另外,在文件引用关系中不能出现互相引用,这样会导至无法编译. 在了解了为什么要计算源代码依赖关系后,就可以开始实现具体的算法了,可以把这一步放在词法分析之后,语法分析之前来做. 因为词法分析之后,可以很容易的分析出一个源文件引用了哪些其它源文件,如果把这一步放在预处理中专门来做的话,同样需要做去注释,拆词等工作,产生了不必要的重复. 计算源代码依赖关系的算法比较简单,可以先把所有源代码文件看成一个个的顶点,一个顶点(源代码文件)如果引用了另一个顶点,就增加一条从当前顶点到被引用顶点的出边,当增加完所有顶点的出边后,正常情况下这些顶点就形成了一个有向无环图如下图:(如果出现了

图的基本存储方法及拓扑排序

实验四 图的基本存储方法及拓扑排序 班级:10级数学班姓名:裴志威学号:201008101127 实验目的: (1)熟练掌握图的基本存储方法; (2)熟练掌握图的深度优先和广度优先搜索方法; (3)掌握AOV网和拓扑排序算法; (4)掌握AOE网和关键路径。 实验内容: 拓扑排序。 任意给定一个有向图,设计一个算法,对它进行拓扑排序。拓扑排序算法思想:a.在有向图中任选一个没有前趋的顶点输出;b.从图中删除该顶点和所有以它为尾的弧;c.重复上述a、b,直到全部顶点都已输出,此时,顶点输出序列即为一个拓朴有序序列;或者直到图中没有无前趋的顶点为止,此情形表明有向图中存在环。 源程序代码: #include #include #define MAXV 10 // 最大顶点个数 typedef struct { int edges[MAXV][MAXV]; // 邻接矩阵的边数组 int n; // 顶点数 }MGraph; typedef struct ANode { int adjvex; // 该弧的终点位置 struct ANode * nextarc; // 指向下一条弧的指针 }ArcNode; typedef struct { int no; // 顶点信息 int count; // 顶点入度 ArcNode * firstarc; // 指向第一条弧 }VNode, AdjList[MAXV];

typedef struct { AdjList adjlist; // 邻接表 int n; // 图的顶点数 }ALGraph; void MatTolist(MGraph g, ALGraph * &G) { int i, j, n=g.n; ArcNode * p; G = (ALGraph *)malloc(sizeof(ALGraph)); for (i=0; iadjlist[i].firstarc = NULL; for (i=0; i=0; j--) if (g.edges[i][j]!=0) { p=(ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = j; p->nextarc = G->adjlist[i].firstarc; G->adjlist[i].firstarc = p; } G->n=n; } void TopSort(ALGraph * G) { int i,j,flag=0,a[MAXV]; int St[MAXV], top = -1; // 栈St的指针为top ArcNode * p; for (i=0; in; i++) // 入度置初值为0 G->adjlist[i].count = 0; for (i=0; in; i++) // 求所有顶点的入度 { p=G->adjlist[i].firstarc; while (p!=NULL) { G->adjlist[p->adjvex].count++; p=p->nextarc; } } for (i=0; in; i++) if (G->adjlist[i].count==0) // 入度为0的顶点进栈 {

拓扑排序实验报告

实验题目: 图的应用 实验目的: (1)熟练掌握图的基本存储方法; (2)熟练掌握图的深度优先和广度优先搜索方法; (3)掌握AOV网和拓扑排序算法; (4)掌握AOE网和关键路径。 实验内容: 拓扑排序。 任意给定一个有向图,设计一个算法,对它进行拓扑排序。拓扑排序算法思想:a. 在有向图中任选一个没有前趋的顶点输出;b.从图中删除该顶点和所有以它为尾的弧;c.重复上述a、b,直到全部顶点都已输出,此时,顶点输出序列即为一个拓朴有序序列;或者直到图中没有无前趋的顶点为止,此情形表明有向图中存在环。 设计分析: 为实现对无权值有向图进行拓扑排序,输出拓扑序列,先考虑如何存储这个有向图。拓扑排序的过程中要求找到入度为0的顶点,所以要采用邻接表来存储有向图,而要得到邻接表,则先要定义有向图的邻接矩阵结构,再把邻接矩阵转化成邻接表。 在具体实现拓扑排序的函数中,根据规则,当某个顶点的入度为0(没有前驱顶点)时,就将此顶点输出,同时将该顶点的所有后继顶点的入度减1,为了避免重复检测入度为0的顶点,设立一个栈St,以存放入度为0的顶点。 源程序代码: #include #include #define MAXV 10 // 最大顶点个数 typedef struct { int edges[MAXV][MAXV]; // 邻接矩阵的边数组 int n; // 顶点数 }MGraph; typedef struct ANode { int adjvex; // 该弧的终点位置

struct ANode * nextarc; // 指向下一条弧的指针}ArcNode; typedef struct { int no; // 顶点信息 int count; // 顶点入度 ArcNode * firstarc; // 指向第一条弧 }VNode, AdjList[MAXV]; typedef struct { AdjList adjlist; // 邻接表 int n; // 图的顶点数 }ALGraph; void MatTolist(MGraph g, ALGraph * &G) { int i, j, n=g.n; ArcNode * p; G = (ALGraph *)malloc(sizeof(ALGraph)); for (i=0; iadjlist[i].firstarc = NULL; for (i=0; i=0; j--) if (g.edges[i][j]!=0) { p=(ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = j; p->nextarc = G->adjlist[i].firstarc; G->adjlist[i].firstarc = p; } G->n=n; } void TopSort(ALGraph * G) { int i,j,flag=0,a[MAXV]; int St[MAXV], top = -1; // 栈St的指针为top ArcNode * p; for (i=0; in; i++) // 入度置初值为0 G->adjlist[i].count = 0; for (i=0; in; i++) // 求所有顶点的入度 {

拓扑排序课程设计报告

拓扑排序课程设计报告

拓扑排序 一目的 通过课程设计,加深对《程序设计语言》和《软件技术基础》课程所学知识的理解,熟练掌握和巩固C语言的基本知识和语法规范,包括:数据类型(整形、实型、字符型、指针、数组、结构等);运算类型(算术运算、逻辑运算、自增自减运算、赋值运算等);程序结构(顺序结构、判断选择结构、循环结构);库函数应用等;复杂任务功能分解方法(自顶向下逐步求精、模块化设计、信息隐藏等),熟练掌握和巩固三种基本图形结构的逻辑结构、存储结构以及相关运算和应用。 学会编制结构清晰、风格良好、数据结构适当的C语言程序,从而具备利用计算机编程分析解决综合性实际问题的初步能力。 二需求分析 题目描述:判断一个有向图是否存在回路,并求出有向无环图的拓扑序列。 1、输入数据 在工程文件中保存输入2个字符串数TXT文

件。第一个为图按次序排列的所有边的前顶点,第二个为相对应的第二个顶点。 2、输出数据 图的定点数,边数,每个顶点的信息及入度,构造的邻接表,图的拓扑排序。 3、程序功能 已将AOV网存入文件中,运行时从文件读取数据;对一个AOV网,应判断其是否是有向无环图,若是则输出其任意一个拓扑排序序列,不是则进行相关的说明;构造图的邻接表;输出所有顶点的入度。 三概要设计 1、全局变量或类型说明 //********结构体定义***********// typedef struct A_Node //定义表结点结构 { int adjvex; //与vi相邻接的顶点编号 struct A_Node *nextarc; //指向下一条弧(边)的指针 } A_Node; typedef struct V_Node //定义表头结点结构 { int data; A_Node *firstarc; //指向第一条弧(边)的指针 } V_Node, AdjList[MAX_NUM]; typedef struct //定义邻接表结构 { AdjList vertices; //表头结点数组 int vex_num, arc_num; //顶点和弧(边)的个数 } ALGraph; typedef struct //构件栈 { Elem_T *base; Elem_T *top; int stacksize; } Sq; 2、模块功能 1)void Init(Sq *S);

相关文档
最新文档