对于关键路径算法实现了一下,下面附上代码 相比于原博文 ,做出了一些调整.
添加链接描述
#include <stdio.h>
#include <stdlib.h>
#define MaxVerNum 20
int visited[MaxVerNum];//访问标志
typedef char VertexType;
typedef struct ArcNode
{
int adjvex; //该弧指向的顶点位置
struct ArcNode * nextarc; //指向下一个表结点
int info; //权值信息
}ArcNode; //边结点类型
typedef struct VNode
{
VertexType data; //顶点的数据域
int indegree; //该顶点的度
ArcNode * firstarc; //该顶点的的第一条邻接边
}VNode, Adjlist[MaxVerNum];
typedef struct
{
Adjlist vertices; //邻接表
int vernum, arcnum; //顶点数和弧数
}ALGraph;
//查找符合的数据在数组中的下标
//返回该顶点在顶点数组中的位置
int LocateVer(ALGraph G, char u)
{
int i;
for(i = 0; i < G.vernum; i++)
{
//就是通过比较数据域是否相等
if(u == G.vertices[i].data)
return i;
}
if(i == G.vernum)
{
printf("Error u!\n");
exit(1);
}
return 0;
}
//常见图的邻接矩阵
void CreateALGraph(ALGraph &G)
{
int i, j, k, w;
char v1, v2;
ArcNode * p;
printf("输入顶点数和弧数: ");
scanf("%d %d", &G.vernum, &G.arcnum); //vernum是值顶点数
printf("请输入顶点!\n");
for(i = 0; i < G.vernum; i++)
{
//挨个输入顶点的信息 输入这个顶点的入度 数据信息 以及第一条边的指针
printf("请输入第 %d 个顶点: \n", i);
fflush(stdin);
scanf("%c", &G.vertices[i].data);
//初始化的时候 将其的入度设置位0,第一条指针设置为空
G.vertices[i].firstarc = NULL;
G.vertices[i].indegree = 0;
}
for(k = 0; k < G.arcnum; k++)
{
printf("请输入弧的顶点和相应权值(v1, v2, w): \n");
//清空输入缓冲区
fflush(stdin);
//输入这条弧对对应顶点 以及这条弧对应的权值
scanf("%c %c %d", &v1, &v2, &w);
//返回这两个顶点在顶点数组中的位置
i = LocateVer(G, v1);
j = LocateVer(G, v2);
//给邻接表指针分配空间
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j; //赋值给p->adjvex指向的顶点域
p->info = w; //边表结点的权值
//这里采用的是头插法 将边插入的边表中去
p->nextarc = G.vertices[i].firstarc;//它的nextarc指针域指向i结点的firstarc指针域
G.vertices[i].firstarc = p;//将点i的第一条指针指向
G.vertices[j].indegree++; //vi->vj, vj入度加1
}
return;
}
//求图的关键路径函数
void CriticalPath(ALGraph G)
{
int i, k, e, l;
int * Ve, * Vl;
ArcNode * p;
//*****************************************
//以下是求时间最早发生时间
//*****************************************
Ve = new int [G.vernum]; //最早发生时间
Vl = new int [G.vernum]; //最迟发生时间
for(i = 0; i < G.vernum; i++) //前推
Ve[i] = 0; //先将最早开始时间全部设置为0
for(i = 0; i < G.vernum; i++)
{
ArcNode * p = G.vertices[i].firstarc;
while(p != NULL)
{
k = p->adjvex;
//找到最大的路径的权值赋值给Ve[K]
if(Ve[i] + p->info > Ve[k])
Ve[k] = Ve[i]+p->info;
p = p->nextarc;
}
}
//*****************************************
//以下是求最迟发生时间
//*****************************************
for(i = 0; i < G.vernum; i++)
Vl[i] = Ve[G.vernum-1];//先将数组初始化位最长路径 就是上面算出来的总路径
for(i = G.vernum-2; i >= 0; i--) //后推
{ //使用从后往前移动的方式 这里i=G.vernum-2开始 是因为G.vernum这个位置位不需要再考虑了 它就是最大值
p = G.vertices[i].firstarc;
while(p != NULL)
{
k = p->adjvex;
//此时通过比较把较小的值赋值给vl[i] 最为最迟开始时间
if(Vl[k] - p->info < Vl[i])
Vl[i] = Vl[k] - p->info;
p = p->nextarc; //遍历找到最小的
}
}
//******************************************
for(i = 0; i < G.vernum; i++)
{
p = G.vertices[i].firstarc;
while(p != NULL)
{ //
k = p->adjvex;
e = Ve[i]; //最早开始时间为时间vi的最早发生时间
l = Vl[k] - p->info; //最迟开始时间 这里用到的减法 表示的是活动的最迟开始时间
//此活动再晚也需要在头顶点是事件发生之前完成
//如果最早时间等于最晚时间 则证明这是关键路径
char tag = (e == l) ? '*' : ' '; //关键活动
printf("(%c, %c), e = %2d, l = %2d, %c\n", G.vertices[i].data, G.vertices[k].data, e, l, tag);
p = p->nextarc;
}
}
delete [] Ve;
delete [] Vl;
}
int main()
{
ALGraph G;
printf("以下是查找图的关键路径的程序。\n");
CreateALGraph(G);
CriticalPath(G);
return 0;
}