数据结构——邻接表表示的图的关键路径算法

#include <iostream>
using namespace std;

#include
<stdio.h>
#include
<stdlib.h>

#define OK 1
#define NULL 0
#define MAX_VERTEX_NUM 20 // 最大顶点数

typedef
char VertexType;
typedef
int VRType;
typedef
int InforType;
typedef
int indegree[MAX_VERTEX_NUM]; //存放节点入度数组
int *ve,*vl; //事件最早发生时间和最迟发生时间数组,全局变量
int *stack2; //建栈存储拓扑序列
int top2;


typedef
struct ArcNode
{
int adjvex; //该边所指的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
int info; //弧的长度(关键路径中的活动)
}ArcNode; //表的结点

typedef
struct VNode
{
VertexType data;
//顶点信息(如数据等)
ArcNode *firstarc; //指向第一条依附该顶点的边的弧指针
}VNode, AdjList[MAX_VERTEX_NUM]; //头结点

typedef
struct ALGraph
{
AdjList vertices;
int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;


//初始化图
void init_ALGraph(ALGraph &g)
{
g.arcnum
=0;
g.vexnum
=0;
}

//返回顶点v在顶点向量中的位置
int LocateVex(ALGraph &G, char v)
{
int i;
for(i = 0; v != G.vertices[i].data && i < G.vexnum; i++)
;
if(i >= G.vexnum)
return -1;
return i;
}

//增加节点
void add_vex(ALGraph &G)
{
cout
<<"输入有向图顶点数: "<<endl;
cin
>>G.vexnum;
//getchar(); //吃回车
cout<<"输入顶点信息:"<<endl;
for(int i = 0; i < G.vexnum; i++)
{
cin
>>G.vertices[i].data; //构造顶点向量
G.vertices[i].firstarc = NULL;
//getchar();
}
}

//增加边
void add_arc(ALGraph &G, indegree indegree)
{
ArcNode
*s;
ArcNode
*p;

for(int k=0; k<G.vexnum; k++)
indegree[k]
=0;

cout
<<"输入有向图边数: "<<endl;
cin
>>G.arcnum;
char v1, v2;
int length;
cout
<<"输入边信息:"<<endl;
for(k = 0; k < G.arcnum; k++)
{
cin
>>v1>>v2>>length;
int i = LocateVex(G, v1);
int j = LocateVex(G, v2); //确定v1 , v2在G中的位置
++indegree[j]; //点j的入度增加1

s
= (ArcNode*) malloc (sizeof(ArcNode));
s
->adjvex = j; //该边所指向的顶点的位置为j
s->info=length;
s
->nextarc = NULL;
if(!G.vertices[i].firstarc)
{
G.vertices[i].firstarc
=s;
}
else
{
for(p = G.vertices[i].firstarc; p->nextarc; p = p->nextarc)
;
p
->nextarc=s;
}
}
}

//构造邻接链表
void CreateUDN(ALGraph &G, indegree indegree)
{
add_vex(G);
//增加节点
add_arc(G,indegree); //增加边
}


void PrintAdjList(ALGraph &G)
{
int i;
ArcNode
*p;
cout
<<"编号 顶点 邻点编号"<<endl;

for(i = 0; i < G.vexnum; i++)
{
cout
<<" "<<i<<" "<<G.vertices[i].data<<" ";
for(p = G.vertices[i].firstarc; p; p = p->nextarc)
cout
<<p->adjvex<<"("<<p->info<<")"<<" ";
cout
<<endl;
}
}

//拓扑排序
int TopologicalSort(ALGraph &g, indegree indegree)
{
//若G无回路,则输出拓扑排序序列并返回1,若有回路返回0。
ArcNode *q;
int i,k;
int gettop;
top2
=0;

ve
=(int *)malloc( g.vexnum*sizeof(int) ); //事件最早发生时间数组
for(i=0; i<g.vexnum; i++)
ve[i]
=0; //初始化

int *stack1; //建栈将入度为0的顶点入栈
stack1=(int *)malloc( g.vexnum*sizeof(int) );
int top1=0;

stack2
=(int *)malloc( g.vexnum*sizeof(int) );//初始化拓扑序列栈

for(i = 0; i<g.vexnum; i++)
if(0 == indegree[i]) //将入度为0的顶点入栈
stack1[++top1]=i;
int count=0;

while(top1!=0)
{
gettop
=stack1[top1--];
cout
<<g.vertices[gettop].data<<"-->";
count
++; //输出i号顶点,并计数

stack2[
++top2]=gettop; //将弹出的顶点序号压入拓扑序列的栈

for(q = g.vertices[gettop].firstarc; q; q = q->nextarc)
{
k
=q->adjvex;
if( !(--indegree[k]) ) //将i号顶点的邻接点的入度减1,如果减1后为0,则入栈
stack1[++top1]=k;
//入栈是求ve
if(ve[gettop] + q->info > ve[k]) //求各顶点事件的最早发生时间ve值
ve[k] = ve[gettop] + q->info;
}
//for
}//while
cout<<endl;
if(count < g.vexnum) //有环路
return 1;
else
return 0;
}


//求关键路径
void CriticalPath(ALGraph &g, indegree indegree) //G为有向网,输出G的各项关键活动
{
ArcNode
*q;
int gettop,k,j;
int ee,el; //活动最早发生时间和最迟发生时间

TopologicalSort(g, indegree);

vl
=(int *)malloc( g.vexnum*sizeof(int) ); //事件最早发生时间数组
for(int i=0; i<g.vexnum; i++)
vl[i]
=ve[g.vexnum-1]; //初始化

cout
<<"ve:"<<endl; //输出ve
for(i=0; i<g.vexnum; i++)
cout
<<ve[i]<<" ";
cout
<<endl;

while(top2!=0) //出栈是求vl
{
gettop
=stack2[top2--];
for(q = g.vertices[gettop].firstarc; q; q = q->nextarc) //求各顶点事件的最迟发生时间vl值
{
k
=q->adjvex;
if(vl[k] - q->info < vl[gettop])
vl[gettop]
= vl[k] - q->info;
}
//for
}

cout
<<"vl:"<<endl; //输出vl
for(i=0; i<g.vexnum; i++)
cout
<<vl[i]<<" ";
cout
<<endl;

for(j=0; j<g.vexnum; j++) //求ee,el和关键活动
{
for(q = g.vertices[j].firstarc; q; q = q->nextarc)
{
k
=q->adjvex;
ee
= ve[j]; //活动最早发生时间
el = vl[k] - q->info; //活动最迟发生时间
if(ee == el) //两者相等即在关键路径上
cout<<g.vertices[j].data<<""<<g.vertices[k].data
<<"长度为:"<<q->info<<"发生时间为"<<ee<<endl;
}
}
}

int main()
{
ALGraph G;
indegree indegree;
init_ALGraph(G);
//初始化图

CreateUDN(G, indegree);
//创建图
PrintAdjList(G); //打印图

CriticalPath(G,indegree);
//求关键路径

return 0;
}

 

posted @ 2010-08-10 19:57  忧国忧铭  Views(1967)  Comments(0Edit  收藏  举报