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

来源:互联网 发布: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;}

原创粉丝点击