数据结构——邻接表表示的图的关键路径算法
来源:互联网 发布:linux rpm svn下载 编辑:程序博客网 时间:2024/06/07 23:47
#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;}