(1)如何判断一个图是不是含有环?
a. DFS,出现返回边则有环。
b. 拓扑排序,若所有的顶点都出现在拓扑排序中,则不出现环。
(2)拓扑排序
a.什么是偏序,全序?from:
http://www.programfan.com/club/showbbs.asp?id=221968
偏序是由实数中的>=和<=抽象出来的
在一个集合F中定义一个比较关系,这个关系不要求任意两个元素都能比较
这个关系可以任意定义,记为<,但是定义的关系要满足以下3个条件
1)任意a属于F,有a<a;...说明元素自己可以和自己比较
2)如果a和b能比较且a<b,b和c能比较,且b<c
那么a和c就能比较,且a<c...说明比较关系具有传递性
3)如果a和b能比较,且a<b,b<a,那么a=b
定义的这种满足以上3条公理的比较关系就叫偏序,和所在的集合记为(F,<)
全序首先是偏序,但是比偏序多一个要求:集合中的任意两个元素都是可比的。
b.拓扑排序:
由偏序定义得到拓扑有序的操作便是拓扑排序(topological order)。
算法:
(1) 在有向图中选一个没有前驱的顶点输出。
(2) 从图中删除该定点和所有以它为尾的弧。
(3) 重复前两步,直至所有节点都输出,或当前图中不存在无前驱的节点(存在环)。
图采用邻接表实现,头文件代码如下:
#defineMAX_VERTEX_NUM20
typedefintInfoType;
typedefcharVertexType;

typedefenum...{DG,DN,UDG,UDN}GraphKind;

typedefstructArcNode...{
intadjvex;
structArcNode*next;
InfoTypeinfo;
}ArcNode;

typedefstructVNode...{
intin_degree;
VertexTypedata;
ArcNode*firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];

typedefstruct...{
AdjListvertex;
intvexnum,arcnum;
GraphKindkind;
}algraph;
源文件代码:
#include"algraph_topo.h"
#include"stdio.h"
#include"stdlib.h"

voidcreateDN(algraph&g)...{}
voidcreateUDN(algraph&g)...{}
voidcreateUDG(algraph&g)...{}
//locatethenamevertice'sindex
intlocate(algraphg,charname)...{
for(inti=0;i<g.vexnum;i++)...{
if(name==g.vertex[i].data)...{
returni;
}
}
return-1;
}

voidcreateDG(algraph&g)...{
printf("inputthenumberofvertexandarcs: ");
scanf("%d%d",&g.vexnum,&g.arcnum);
fflush(stdin);
inti=0,j=0,k=0;
printf("inputthenameofvertex: ");

for(i=0;i<g.vexnum;i++)...{
scanf("%c",&g.vertex[i].data);
fflush(stdin);
g.vertex[i].firstarc=NULL;
g.vertex[i].in_degree=0;
}
//constructtheadjacentlist
charv1,v2;
intw;
ArcNode*p;
printf("inputthe%darcsv1v2andweight: ",g.arcnum);
for(k=0;k<g.arcnum;k++)...{
scanf("%c%c%d",&v1,&v2,&w);
fflush(stdin);
i=locate(g,v1);
j=locate(g,v2);
//newanode
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info=w;
p->next=NULL;
//insertthenodeintheheadoflist
if(!g.vertex[i].firstarc)...{
g.vertex[i].firstarc=p;
}else...{
p->next=g.vertex[i].firstarc;
g.vertex[i].firstarc=p;
}
g.vertex[j].in_degree++;
}
}
//printthelist
voidprintGraph(algraphg)...{
for(inti=0;i<g.vexnum;i++)...{
printf("%c'sadjacentlistis: ",g.vertex[i].data);
ArcNode*p=g.vertex[i].firstarc;
while(p)...{
printf("%c(%d) ",g.vertex[p->adjvex].data,p->info);
p=p->next;
}
printf(" ");
}
}

voidcreateGragh(algraph&g)...{
printf("pleaseinputthetypeofgraph: ");
scanf("%d",&g.kind);

switch(g.kind)...{
caseDG:
createDG(g);
//printGraph(g);
break;
caseDN:
createDN(g);
break;
caseUDG:
createUDG(g);
break;
caseUDN:
createUDN(g);
break;
}
}
//²éÕÒÏÂÒ»¸ö
intfindNext(algraphg)...{
for(inti=0;i<g.vexnum;i++)...{
if(g.vertex[i].in_degree==0)...{
returni;
}
}
return-1;
}
//topoorder
voidtopoSort(algraphg)...{
printf("thetoposortofgraphis: ");
for(inti=0;i<g.vexnum;i++)...{
intindex=findNext(g);
if(index>-1)...{
printf("%c ",g.vertex[index].data);
//don'tconsidertheverticeagain
g.vertex[index].in_degree=-1;
ArcNode*p=g.vertex[index].firstarc;
while(p)...{
g.vertex[p->adjvex].in_degree--;
p=p->next;
}
}else...{
break;
}
}
printf(" ");
}

voidmain()...{
algraphg;
createGragh(g);
topoSort(g);
}
程序的运行结果如下:
pleaseinputthetypeofgraph:
0
inputthenumberofvertexandarcs:
68
inputthenameofvertex:
a
b
c
d
e
f
inputthe8arcsv1v2andweight:
ad1
ac1
ab1
ce1
cb1
de1
fe1
fd1
thetoposortofgraphis:
acbfde
Pressanykeytocontinue
说明:
(1) 为了避免重复检测入度为0的顶点,可设置一个栈暂存所有入度为0的顶点,复杂度为O(n + e)。而在程序中采用的是
//don'tconsidertheverticeagain
g.vertex[index].in_degree=-1;
来实现的。复杂度要高一些。
(2) 可以使用DFS,退出DFS函数的顺序即为逆向的拓扑有序序列。
(3)关键路径
a. AOV网:用顶点表示活动,用弧表示活动间的优先关系的有向图称为顶点表示活动的网(activity on vertex network)。AOV网中,没有有向环。
b. AOE网:边表示活动的网络(顶点表示事件,弧表示活动),用来估算工程的完成时间,通常只有一个源点和一个汇点。
c. 求AOE算法的复杂度是O(n + e)
图算法精讲
4465

被折叠的 条评论
为什么被折叠?



