标签:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <malloc.h> 4 5 #define MAXVEX 30 //最大顶点数 6 #define MAXEDGE 30 //最大边数 7 #define INFINITY 65535 //∞ 8 9 //定义全局变量 10 int *etv, *ltv;//事情最早发生和最迟发生指针数组 11 int *stack2;//用于存储拓扑排序的栈 12 int top2;//用于指向stack2栈指针 13 14 /* 邻接矩阵结构 */ 15 typedef struct 16 { 17 int vexs[MAXVEX];//顶点下标 18 int arc[MAXVEX][MAXVEX];//矩阵(路径) 19 int numVertexes, numEdges;//当前图中的顶点数和边数 20 }MGraph; 21 22 23 /* 邻接表结构 */ 24 typedef struct EdgeNode // 25 {//边表结点 26 int adjvex;//顶点下标 27 int weight;//路径 28 struct EdgeNode *next;//指向想一个边表结点 29 }EdgeNode; 30 31 typedef struct VertexNode 32 {//顶点结点 33 int in;//入度 34 int data;//顶点信息 35 EdgeNode *firstedge;//指向边表头指针 36 }VertexNode, AdjList[MAXVEX]; 37 38 typedef struct 39 { 40 AdjList adjList;//顶点向量 41 int numVertexes, numEdges;//顶点数和边数 42 }graphAdjList, *GraphAdjList; 43 44 45 46 void CreateMGraph(MGraph *G) 47 {/* 构建图 */ 48 int i, j; 49 50 // printf("请输入顶点数和边数:\n"); 51 G->numVertexes = 10; 52 G->numEdges = 13; 53 54 //初始化顶点下标 55 for(i=0; i<G->numVertexes; i++) 56 G->vexs[i] = i; 57 58 //初始化矩阵 59 for(i=0; i<G->numVertexes; i++) 60 for(j=0; j<G->numVertexes; j++) 61 if(i == j) 62 G->arc[i][j] = 0; 63 else 64 G->arc[i][j] = INFINITY; 65 66 //内置输入 67 G->arc[0][1] = 3; 68 G->arc[0][2] = 4; 69 G->arc[1][3] = 5; 70 G->arc[1][4] = 6; 71 G->arc[2][3] = 8; 72 G->arc[2][5] = 7; 73 G->arc[3][4] = 3; 74 G->arc[4][6] = 9; 75 G->arc[4][7] = 4; 76 G->arc[5][7] = 6; 77 G->arc[6][9] = 2; 78 G->arc[7][8] = 5; 79 G->arc[8][9] = 3; 80 81 return ; 82 } 83 84 85 86 void CreateALGraph(MGraph G, GraphAdjList *GL) 87 {/* 利用邻接矩阵,构建邻接表 */ 88 int i, j; 89 EdgeNode *e; 90 91 *GL = (GraphAdjList)malloc(sizeof(graphAdjList));//*GL代表主函数的GL指向 92 (*GL)->numVertexes = G.numVertexes;/* 读取信息 */ 93 (*GL)->numEdges = G.numEdges; 94 95 //初始化 96 for(i=0; i<G.numVertexes; i++) 97 { 98 (*GL)->adjList[i].in = 0; 99 (*GL)->adjList[i].data = G.vexs[i];//读取顶点下标 100 (*GL)->adjList[i].firstedge = NULL; 101 } 102 103 //构建邻接表 104 for(i=0; i<G.numVertexes; i++) 105 for(j=0; j<G.numVertexes; j++) 106 if(0 != G.arc[i][j] && INFINITY > G.arc[i][j]) 107 {//若存在路径 108 e = (EdgeNode *)malloc(sizeof(EdgeNode));//申请 109 e->adjvex = j;//存顶点 110 e->weight = G.arc[i][j];//存路径 111 e->next = (*GL)->adjList[i].firstedge;//存表头指针 112 (*GL)->adjList[i].firstedge = e;//头插 113 (*GL)->adjList[j].in ++;//顶点入度+1 114 } 115 return ; 116 } 117 118 119 120 void TopologicalSort(GraphAdjList GL) 121 {/* 拓扑排序 */ 122 EdgeNode *e; 123 int i, gettop, k; 124 int top = 0;//用于指向stack栈顶 125 int count = 0;//技术输出 126 int *stack;//建栈存储入度位0的顶点 127 stack = (int *)malloc(sizeof(int)); 128 for(i=0; i<GL->numVertexes; i++)//把所有入度位0的顶点如stack栈中 129 if(0 == GL->adjList[i].in) 130 stack[++top] = i; 131 132 etv = (int *)malloc(sizeof(int) * GL->numVertexes);//最早发生etv指针申请空间 133 for(i=0; i<GL->numVertexes; i++)//初始化最早发生etv数组 134 etv[i] = 0; 135 136 stack2 = (int *)malloc(sizeof(int) * GL->numVertexes);//存储拓扑排序序列 137 top2 = 0;//用于指向stack2栈顶 138 printf("Topological:\t"); 139 while(0 != top) 140 {//若有顶点入度为0 141 gettop = stack[top--];//出栈 142 printf("%3d->", GL->adjList[gettop].data);//输出出栈的栈顶的顶点信息 143 count ++;//输出记数 144 145 stack2[++top2] = gettop;//出栈元素赋给存储拓扑序列栈 146 147 for(e=GL->adjList[gettop].firstedge; e; e=e->next) 148 {//出栈的栈顶元素若有邻接点 149 k = e->adjvex;//邻接点-顶点下标 150 if(! (--GL->adjList[k].in))//邻接点顶点下标-1(gettop已指向),是否入度位0? 151 stack[++top] = k;//是则入stack的栈 152 153 /*出栈的最早发生时间值+出栈邻接表的路径 > 出栈邻接表顶点下标的最早发生时间值 154 就是v0-v1-v3和v0-v2-v3都是从起点到达汇点,3哪一个路径较远 */ 155 if((etv[gettop] + e->weight) > etv[k]) 156 etv[k] = etv[gettop] + e->weight; 157 } 158 } 159 printf("\n"); 160 161 if(count < GL->numVertexes)//若有环,则结束程序 162 exit(-1); 163 164 return ; 165 } 166 167 168 169 void CriticalPath(GraphAdjList GL) 170 {/* 关键路径 */ 171 EdgeNode *e; 172 int i, gettop, k, j; 173 int ete, lte;//最早发生和最迟发生的变量 174 175 TopologicalSort(GL);//调用拓扑排序函数 176 177 ltv = (int *)malloc(sizeof(int) * GL->numVertexes);//最迟发生指针边表指向申请空间 178 for(i=0; i<GL->numVertexes; i++)//初始化最迟发生数组 179 ltv[i] = etv[GL->numVertexes - 1];//起到汇最大值 180 181 //输出最早发生数组 182 printf("etv:\t\t"); 183 for(i=0; i<GL->numVertexes; i++) 184 printf("%3d->", etv[i]); 185 printf("\n"); 186 187 while(0 != top2) 188 {//存放拓扑排序数列 189 gettop = stack2[top2--]; 190 for(e=GL->adjList[gettop].firstedge; e; e=e->next) 191 { 192 k = e->adjvex; 193 if((ltv[k] - e->weight) < ltv[gettop]) 194 ltv[gettop] = ltv[k] - e->weight; 195 /*最晚发生时间值(出stack2(存拓扑排序)栈元素的邻接点顶点下标) - 邻接路径 < 最晚发生数组【出栈元素0】 196 用拓扑排序的最长路径 - 邻接路径 < 最晚发生值[出栈元素]*/ 197 } 198 } 199 200 printf("ltv:\t\t");//输出最晚值数组 201 for(i=0; i<GL->numVertexes; i++) 202 printf("%3d->", ltv[i]); 203 printf("\n"); 204 205 for(j=0; j<GL->numVertexes; j++) 206 for(e=GL->adjList[j].firstedge; e; e=e->next) 207 { 208 k = e->adjvex; 209 ete = etv[j];//最早发生时间 210 lte = ltv[k] - e->weight;//最迟发生时间 211 212 if(ete == lte)//相等即在关键路径上 213 printf("<v%d - v%d> length : %d \n", GL->adjList[j].data, GL->adjList[k].data, e->weight); 214 } 215 216 return ; 217 } 218 219 int main(void) 220 221 { 222 MGraph G; 223 GraphAdjList GL; 224 system("title 关键路径"); 225 CreateMGraph(&G); 226 CreateALGraph(G, &GL); 227 CriticalPath(GL); 228 229 return 0; 230 }
标签:
原文地址:http://www.cnblogs.com/bebug/p/4331155.html