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

  
    
#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 ;
}

 

你可能感兴趣的:(数据结构)