1.有向无环图的用处
- 有向无环图是描述含有公共子式的表达式的有效工具
- 有向图是描述一项工程或系统过程控制的有效工具
2.AOV网络以及拓扑排序
2.1. AOV网络
顶点是活动,弧表示优先关系。
2.2. 拓扑序列
将弧尾的结点拍在弧头的前面,没有优先关系的都无所谓。计算机是从小到大。
【算法实现】
//AOV网图及拓扑排序
int top_sort(ALGraph G)
{
Stack S; StackInit(&S);//初始化顺序栈
int m = 0;
for (int i = 0; i < G.arcNum; i++)
if (G.adjlist[i].id == 0)StackPush(&S, i);
while (!StackEmpty(&S))
{
int v = StackTop(&S); StackPop(&S);
m++;
ArcNode* p = G.adjlist[v].firstArc;
while (p != NULL)
{
int w = p->adjvex; G.adjlist[w].id--;
if (G.adjlist[w].id == 0)StackPush(&S, w);
p = p->nextArc;
}
}
if (m < G.vexNum)
{
StackDestroy(&S);
return 0;
}
return 0;
StackDestroy(&S);
}
3.AOE网络及关键路径
【算法实现】
//求关键路径的算法
void critical_patch( ALGraph G)
{
//为求ve[i],用栈s1存放入度为0的顶点序号
//为求vl[i],用栈s2存放拓扑序列的顶点序号
Stack s1, s2; StackInit(&s1); StackInit(&s2);
int i = 0, j = 0, k = 0, ve[20] = { 0 }, vl[20] = { 0 }, ee = 0, el = 0;
ArcNode* p = NULL;
char tag = 0;
findiInDegree(G);//求各个顶点的入度
for (i = 0; i < G.vexNum; i++)//入度为0的顶点序号进栈
if (G.adjlist[i].id == 0)StackPush(&s1, i);
for (i = 0; i < G.vexNum; i++)ve[i] = 0;//ve初始化
//按拓扑序列求各顶点的ve值,对每一条弧求弧头的ve,弧头取最大值
while (!StackEmpty(&s1))//在拓扑排序的过程中求ve
{
j = StackTop(&s1); StackPop(&s1);//取拓扑序列顶点序号
StackPush(&s2, j);//存拓扑序列顶点序号
p = G.adjlist[j].firstArc;
while (p != NULL)//处理弧<j,k>,求弧头k的ve
{
k = p->adjvex;
G.adjlist[k].id--;
if (G.adjlist[k].id == 0)StackPush(&s1, k);
if (ve[j] + p->weight > ve[k])ve[k] = ve[j] + p->weight;
p = p->nextArc;
}//end_while(p!=NULL)
}//end_while (!StackEmpty(&s1)),求ve[j]完成
//用ve(汇点)对vl进行初始化
for (i = 0; i < G.vexNum; i++)vl[i] = ve[s2._top];
//按逆拓扑序列求各顶点的vl值,对每一个条弧求弧尾的vl,弧尾相同的取最小值
while (!StackEmpty(&s2))
{
j = StackTop(&s2); StackPop(&s2);
p = G.adjlist[j].firstArc;
while (p != NULL)//处理弧<j,k>,求弧尾的vl
{
k = p->adjvex;
if (vl[k] - p->weight < vl[j])vl[j] = vl[k] - p->weight;
p = p->nextArc;
}//end_while (p != NULL)
}//end_while (!StackEmpty(&s2)),求vl[j]完成
//已知ve[i]、vl[i],求ee和el
//第i条弧<j,k>的ee(i)=ve(j),el(i)=vl(k)-weight(<j,k>)
for (j = 0; j < G.vexNum; j++)
{
p = G.adjlist[j].firstArc;
while (p != NULL)
{
k = p->adjvex;
ee = ve[j]; el = vl[k] - p->weight;
if (ee == el)tag = 'y';//标记关键活动
else tag = 'n';
printf("活动:%c->%c ee=%-4d el=%-4d %c\n", G.adjlist[j].vertex, G.adjlist[k].vertex, ee, el, tag);
p = p->nextArc;
}//end_while
}//end_for
}