数据结构 图 有向无环图

(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

typedef
intInfoType;
typedef
charVertexType;

typedef
enum...{DG,DN,UDG,UDN}GraphKind;

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

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

typedef
struct...{
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
inputthe
8arcsv1v2andweight:
ad
1
ac
1
ab
1
ce
1
cb
1
de
1
fe
1
fd
1
thetoposortofgraph
is:
acbfde
Pressanykeyto
continue

说明:

(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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值