【数据结构】关键路径

来源:互联网 发布:雷霆战机觉醒矩阵 编辑:程序博客网 时间:2024/05/17 00:00

关键路径

数据结构中 求关键路径,以前写的代码,传给大家看看!


/*名称:关键路径 语言:数据结构C语言版 编译环境:VC++ 6.0日期:2014-3-25 */#include <stdio.h>  #include <limits.h>  #include <malloc.h>      #include<cstdlib>   #include <string.h>//  求关键路径。实现算法7.13、7.14的程序 // 图的邻接表存储表示 #define MAX_NAME 3// 顶点字符串的最大长度+1 #define MAX_VERTEX_NUM 20typedef int InfoType;// 存放网的权值 typedef char VertexType[MAX_NAME];// 字符串类型 typedef enum{DG,DN,AG,AN}GraphKind; // {有向图,有向网,无向图,无向网} typedef struct ArcNode{int adjvex;// 该弧所指向的顶点的位置 struct ArcNode *nextarc;// 指向下一条弧的指针 InfoType *info;// 网的权值指针) }ArcNode;// 表结点 typedef struct VNode{VertexType data;// 顶点信息 ArcNode *firstarc;// 第一个表结点的地址,指向第一条依附该顶点的弧的指针  }VNode,AdjList[MAX_VERTEX_NUM];// 头结点 typedef struct{AdjList vertices;int vexnum,arcnum;// 图的当前顶点数和弧数 int kind;// 图的种类标志 }ALGraph;int ve[MAX_VERTEX_NUM]; // 全局变量(用于算法7.13和算法7.14) // 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。 int LocateVex(ALGraph G,VertexType u){int i;for(i=0;i<G.vexnum;++i)if(strcmp(u,G.vertices[i].data)==0)return i;return -1;}// 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图)。int CreateGraph(ALGraph *G){int i,j,k;int w;// 权值 VertexType va,vb;ArcNode *p;printf("请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3): ");scanf("%d",&(*G).kind);printf("请输入图的顶点数和边数:(空格)\n");scanf("%d%d", &(*G).vexnum, &(*G).arcnum);printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME);for(i = 0; i < (*G).vexnum; ++i)// 构造顶点向量 {scanf("%s", (*G).vertices[i].data);(*G).vertices[i].firstarc = NULL;}if((*G).kind == 1 || (*G).kind == 3) // 网 printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n");else // 图 printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):\n");for(k = 0;k < (*G).arcnum; ++k)// 构造表结点链表 {if((*G).kind==1||(*G).kind==3) // 网 scanf("%d%s%s",&w,va,vb);else// 图 scanf("%s%s",va,vb);i = LocateVex(*G,va); // 弧尾 j = LocateVex(*G,vb); // 弧头 p = (ArcNode*)malloc(sizeof(ArcNode));p->adjvex = j;if((*G).kind == 1 || (*G).kind == 3) // 网 {p->info = (int *)malloc(sizeof(int));*(p->info) = w;}elsep->info = NULL; // 图 p->nextarc = (*G).vertices[i].firstarc; // 插在表头 (*G).vertices[i].firstarc = p;if((*G).kind >= 2) // 无向图或网,产生第二个表结点 {p = (ArcNode*)malloc(sizeof(ArcNode));p->adjvex = i;if((*G).kind == 3) // 无向网 {p->info = (int*)malloc(sizeof(int));*(p->info) = w;}elsep->info = NULL; // 无向图 p->nextarc = (*G).vertices[j].firstarc; // 插在表头 (*G).vertices[j].firstarc = p;}}return 1;}//输出图的邻接表G。void Display(ALGraph G){int i;ArcNode *p;switch(G.kind){case DG: printf("有向图\n");break;case DN: printf("有向网\n");break;case AG: printf("无向图\n");break;case AN: printf("无向网\n");}printf("%d个顶点:\n",G.vexnum);for(i = 0; i < G.vexnum; ++i)printf("%s ",G.vertices[i].data);printf("\n%d条弧(边):\n", G.arcnum);for(i = 0; i < G.vexnum; i++){p = G.vertices[i].firstarc;while(p){if(G.kind <= 1) // 有向 {printf("%s→%s ",G.vertices[i].data,G.vertices[p->adjvex].data);if(G.kind == DN) // 网 printf(":%d ", *(p->info));}else// 无向(避免输出两次) {if(i < p->adjvex){printf("%s-%s ",G.vertices[i].data,G.vertices[p->adjvex].data);if(G.kind == AN)// 网 printf(":%d ",*(p->info));}}p=p->nextarc;}printf("\n");}}// 求顶点的入度,算法7.12、7.13调用void FindInDegree(ALGraph G,int indegree[]){int i;ArcNode *p;for(i=0;i<G.vexnum;i++)indegree[i]=0; // 赋初值 for(i=0;i<G.vexnum;i++){p=G.vertices[i].firstarc;while(p){indegree[p->adjvex]++;p=p->nextarc;}}}typedef int SElemType; // 栈类型#define STACK_INIT_SIZE 10// 存储空间初始分配量 #define STACKINCREMENT 2// 存储空间分配增量 // 栈的顺序存储表示 P46 typedef struct SqStack{SElemType *base;// 在栈构造之前和销毁之后,base的值为NULL SElemType *top;// 栈顶指针 int stacksize;// 当前已分配的存储空间,以元素为单位 }SqStack;// 顺序栈//构造一个空栈S。int InitStack(SqStack *S){// 为栈底分配一个指定大小的存储空间(*S).base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if( !(*S).base )exit(0);// 存储分配失败 (*S).top = (*S).base;// 栈底与栈顶相同表示一个空栈(*S).stacksize = STACK_INIT_SIZE;return 1;}// 若栈S为空栈(栈顶与栈底相同的),则返回1,否则返回0。int StackEmpty(SqStack S){if(S.top == S.base)return 1;elsereturn 0;}//插入元素e为新的栈顶元素。int Push(SqStack *S, SElemType e){if((*S).top - (*S).base >= (*S).stacksize)// 栈满,追加存储空间 {(*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));if( !(*S).base )exit(0); // 存储分配失败 (*S).top = (*S).base+(*S).stacksize;(*S).stacksize += STACKINCREMENT;}*((*S).top)++=e;// 这个等式的++ * 优先级相同,但是它们的运算方式,是自右向左return 1;}//若栈不空,则删除S的栈顶元素,用e返回其值,并返回1;否则返回0。int Pop(SqStack *S,SElemType *e){if((*S).top == (*S).base)return 0;*e = *--(*S).top;// 这个等式的++ * 优先级相同,但是它们的运算方式,是自右向左return 1;}// 算法7.13  P185// 有向网G采用邻接表存储结构,求各顶点事件的最早发生时间ve (全局变量)。// T为拓扑序列顶点栈,S为零入度顶点栈。若G无回路,则用栈T返回G的一个拓// 扑序列,且函数值为1,否则为0 int TopologicalOrder(ALGraph G,SqStack *T){int j,k,count,indegree[MAX_VERTEX_NUM];SqStack S;ArcNode *p;FindInDegree(G,indegree);//对各顶点求入度indegree[0..vernum-1] InitStack(&S); // 初始化栈 for(j=0;j<G.vexnum;++j) // 建零入度顶点栈S if(!indegree[j])Push(&S,j); // 入度为0者进栈 InitStack(T); // 初始化拓扑序列顶点栈 count=0; // 对输出顶点计数 for(j=0;j<G.vexnum;++j) // 初始化ve[]=0 (最小值) ve[j]=0;while(!StackEmpty(S)){// 栈不空 Pop(&S,&j);Push(T,j); // j号顶点入T栈并计数 ++count;for(p=G.vertices[j].firstarc;p;p=p->nextarc){// 对j号顶点的每个邻接点的入度减1 k=p->adjvex;if(--indegree[k]==0) // 若入度减为0,则入栈 Push(&S,k);if(ve[j]+*(p->info)>ve[k])ve[k]=ve[j]+*(p->info);}}if(count<G.vexnum){printf("此有向网有回路\n");return 0;}elsereturn 1;}// 算法7.14 P185// G为有向网,输出G的各项关键活动int CriticalPath(ALGraph G){ int vl[MAX_VERTEX_NUM];SqStack T;int i,j,k,ee,el;ArcNode *p;char dut,tag;if(!TopologicalOrder(G,&T)) // 产生有向环 return 0;j=ve[0];for(i=1;i<G.vexnum;i++) // j=Max(ve[]) 完成点的值 if(ve[i]>j)j=ve[i];for(i=0;i<G.vexnum;i++) // 初始化顶点事件的最迟发生时间(最大值) vl[i]=j; // 完成点的最早发生时间 while(!StackEmpty(T)) // 按拓扑逆序求各顶点的vl值 for(Pop(&T,&j),p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;dut=*(p->info); // dut<j,k> if(vl[k]-dut<vl[j])vl[j]=vl[k]-dut;}printf(" j  k  dut  ee  el  tag\n");for(j=0;j<G.vexnum;++j) // 求ee,el和关键活动 for(p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;dut=*(p->info);ee=ve[j];el=vl[k]-dut;tag=(ee==el)?'*':' ';// 输出关键活动printf("%2d %2d %3d %3d %3d    %c\n",j,k,dut,ee,el,tag); }printf("关键活动为:\n");for(j=0;j<G.vexnum;++j) // 同上 for(p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;dut=*(p->info);if(ve[j]==vl[k]-dut)// 输出关键活动 printf("%s→%s\n",G.vertices[j].data,G.vertices[k].data); }return 1;}int main(){ALGraph h;printf("请选择有向网\n");CreateGraph(&h);Display(h);CriticalPath(h);system("pause");return 0;}/*输出效果:请选择有向网请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3): 1请输入图的顶点数和边数:(空格)6 8请输入6个顶点的值(<3个字符):v1v2v3v4v5v6请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):3 v1 v22 v1 v32 v2 v43 v2 v54 v3 v43 v3 v62 v4 v61 v5 v6有向网6个顶点:v1 v2 v3 v4 v5 v68条弧(边):v1→v3 :2 v1→v2 :3v2→v5 :3 v2→v4 :2v3→v6 :3 v3→v4 :4v4→v6 :2v5→v6 :1 j  k  dut  ee  el  tag 0  2   2   0   0    * 0  1   3   0   1 1  4   3   3   4 1  3   2   3   4 2  5   3   2   5 2  3   4   2   2    * 3  5   2   6   6    * 4  5   1   6   7关键活动为:v1→v3v3→v4v4→v6请按任意键继续. . . */


2 0
原创粉丝点击