编程实现关键路径的算法

#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 20//顶点最大个数


typedef int Status;//函数的类型,其值是函数结果状态代码
typedef char VertexType;//顶点元素的类型
typedef int ElemType;


typedef struct ArcNode
{
    int adjvex;//该弧所指的顶点的位置
    struct ArcNode *nextarc;//指向下一条狐的指针
    int weight;//边的权
}ArcNode;//表的结点


typedef struct Vnode
{
    VertexType data;
    ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];


typedef struct
{
 AdjList vertices;
 int vexnum,arcnum;
 int kind;//图的种类
 }ALGraph;


 typedef struct SqStack
 {
     ElemType elem[MAX_VERTEX_NUM];
     int top;
 }SqStack;


 //初始化栈
 void InitStack(SqStack &S)
 {
     S.top=-1;
 }
 //判断栈空否,1为空
 Status StackEmpty(SqStack S)
 {
     if(S.top==-1)
     return 1;
     else
     return 0;
 }
 //入栈
 Status Push(SqStack &S,ElemType e)
 {
     if(S.top==MAX_VERTEX_NUM-1)
     return 0;
     S.elem[++S.top]=e;
     return 1;


 }
 //栈顶元素出栈
 Status Pop(SqStack &S,ElemType *e)
 {
     if(S.top==-1)
     return 0;
     *e=S.elem[S.top--];
     return 1;
 }


 //返回顶点v在图顶点向量中的位置
 int LocateVex(ALGraph G,char v)
 {
      int i;
     for(int i=0;v!=G.vertices[i].data&&i<G.vexnum;++i);
     if(i>=G.vexnum)
     return -1;
     return i;
     }
   //建立邻接表
   void creatDN(ALGraph &G)
 {
     int i,j,w;
     char v1,v2;
     ArcNode *s;
     printf("输入图的顶点数:");
     scanf("%d",&G.vexnum);
     printf("输入图的边数:");
     scanf("%d",&G.arcnum);
     for(i=0;i<G.vexnum;i++)
     {
         printf("输入第%d的顶点的信息:",i+1);
         scanf("%s",&G.vertices[i].data);
         G.vertices[i].firstarc=NULL;
     }
     for(int i1=0;i1<G.arcnum;i1++)//该弧所指的顶点的位置
     {
         printf("输入第%d个活动的先序顶点:",i1+1);
         scanf("%s",&v1);
         printf("输入第%d个活动的后序顶点:",i1+1);
         scanf("%s",&v2);
         printf("输入这个活动的时间:",i1+1);
         scanf("%d",&w);
         i=LocateVex(G,v1);
         j=LocateVex(G,v2);
         s=(ArcNode *)malloc(sizeof(ArcNode));
         s->adjvex=j;//弧所指的顶点的位置为j
         s->weight=w;
         s->nextarc=G.vertices[i].firstarc;
         G.vertices[i].firstarc=s;
     }
 }
 //输出邻接表
 void printAdjList(ALGraph G)
     {
      int i;
      ArcNode *p;
      printf("%4s%6s%12s\n","编号","顶点","相邻边编号");
      for(i=0;i<G.vexnum;i++)
      {
          printf("%4d%5c",i,G.vertices[i].data);
          for(p=G.vertices[i].firstarc;p;p=p->nextarc)
          printf("%3d",p->adjvex);//弧所指的顶点的位置
          printf("\n");


      }
     }
     //对顶点求入度,需要遍历邻接矩阵
     void FindInDegree(ALGraph G,int *indegree)
     {
         ArcNode *s;
         for(int i=0;i<G.vexnum;i++)
         {
             s=G.vertices[i].firstarc;
             while(s)
             {
                 indegree[s->adjvex]++;
                 s=s->nextarc;
             }
         }
     }
     //拓扑排序
     int ve[MAX_VERTEX_NUM];
     int TopologicalOrder(ALGraph G,SqStack &T)
     {
         SqStack S;
         int i,k,count,*indegree;
         ArcNode *P;
         indegree=(int *)malloc(G.vexnum*sizeof(int));//顶点入度数组
         for(i=0;i<G.vexnum;i++)
         indegree[i]=0;
         FindInDegree(G,indegree);//求各点入度
         InitStack(S);
         InitStack(T);//初始化栈
         for(i=0;i<G.vexnum;i++)
         if(!indegree[i])Push(S,i);
         count=0;
         for(i=0;i<G.vexnum;i++)
         ve[i]=0;
         while(!StackEmpty(S))
         {
             Pop(S,&i);//拿出入度为0的顶点
             Push(T,i);
             ++count;
             ArcNode *p;
             for(p=G.vertices[i].firstarc;p;p=p->nextarc)
             {
                 k=p->adjvex;
                 if(!(--indegree[k]))
                 Push(S,k);
                 if(ve[i]+p->weight>ve[k])
                 ve[k]=ve[i]+p->weight;
             }
         }
         if(count<G.vexnum)
         return 0;
         else
         return 1;
     }
     //图G为有向图,输出G中的关键活动
     int CriticalPath(ALGraph G)
     {
         int v1[MAX_VERTEX_NUM];
         SqStack T;
         int i,j,k,dut,ee,e1;
         char tag;
         ArcNode *p;
         if(!TopologicalOrder(G,T))
         return 0;
         for(i=0;i<G.vexnum;i++)
         v1[i]=ve[G.vexnum-1];//初始化顶点事件的最迟发生时间
         while(!StackEmpty(T))//按拓扑排序逆序求各个顶点的v1值
          for(Pop(T,&j),p=G.vertices[j].firstarc;p;p=p->nextarc)
         {
             k=p->adjvex;
             dut=p->weight;
             if(v1[k]-dut<v1[j])
             v1[j]=v1[k]-dut;
         }
         printf("(vi,vj)dut ee e1(*)\n");
         for(j=0;j<G.vexnum;j++)//求ee,e1和关键活动
           for(p=G.vertices[j].firstarc;p;p=p->nextarc)
         {
             k=p->adjvex;
             dut=p->weight;
             ee=ve[j];
             e1=v1[k]-dut;
             tag=(ee==e1)? '*':' ';
             printf("(%c,%c)%d %d %d %c\n",G.vertices[j].data,G.vertices[k].data,dut,ee,e1,tag);
         }
         printf("顶点i ve(i) v1(i)\n");
         for(j=0;j<G.vexnum;j++)
         printf("%5c%5d%5d\n",G.vertices[j].data,ve[j],v1[j]);
         return 1;
     }
     int main()
     {
         ALGraph G;
         creatDN(G);//构造图的邻接表
         printAdjList(G);//输出邻接表
         printf("标*的活动为图G关键路径上的活动\n");
         CriticalPath(G);//求图G的关键路径
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值