#include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 10 #define MAX_STACK_VOLUME 30 typedef struct ArcNode { // Arc structure int adjvex; struct ArcNode *nextarc; int weight; }ArcNode; typedef struct VNode { // Vertex structure int data; ArcNode *firstarc; }VNode, AdjList[MAX_VERTEX_NUM]; typedef struct { // Adjacency List structure AdjList vertices; int vexnum; int arcnum; }ALGraph; typedef struct { // The most simple stack structure int stack[MAX_STACK_VOLUME]; int top; }Stack; /* These functions are prepared for stack */ void initStack(Stack *s) { int i; s->top = 0; for (i = 0; i < MAX_STACK_VOLUME; i++) { s->stack[i] = -1; } } void push(Stack *s, int value) { s->stack[s->top] = value; s->top++; } int pop(Stack *s) { if (s->top == 0) { printf("Stack had been empty\n"); return -1; } return s->stack[--s->top]; } int empty(Stack s) { return (s.top == 0) ? 1 : 0; } /* These functions are prepared for ALGraph */ void createArc(ALGraph *alg, int start_v, int end_v, int weight) { // Create arc for adjacency list ArcNode *p_read = alg->vertices[start_v].firstarc; ArcNode *p_new = (ArcNode *)malloc(sizeof(ArcNode)); p_new->adjvex = end_v; p_new->weight = weight; p_new->nextarc = NULL; if (p_read != NULL) { while (p_read->nextarc != NULL) { p_read = p_read->nextarc; } p_read->nextarc = p_new; } else { alg->vertices[start_v].firstarc = p_new; } } void createALG(ALGraph *alg, int vexnum, int arcnum) { // Create adjacency list for sample alg->vexnum = vexnum; alg->arcnum = arcnum; int i; for (i = 0; i < vexnum; i++) { alg->vertices[i].firstarc = NULL; } createArc(alg, 0, 1, 6); createArc(alg, 0, 2, 4); createArc(alg, 0, 3, 5); createArc(alg, 1, 4, 1); createArc(alg, 2, 4, 1); createArc(alg, 3, 5, 2); createArc(alg, 4, 6, 9); createArc(alg, 4, 7, 8); createArc(alg, 5, 7, 4); createArc(alg, 6, 8, 2); createArc(alg, 7, 8, 4); } void showALG(ALGraph alg) { // Show ALGraph's adjacency list printf("Show ALGraph: \n"); int i; for (i = 0; i < alg.vexnum; i++) { ArcNode *p_read = alg.vertices[i].firstarc; if (p_read == NULL) printf("V%d\n", i); else { printf("V%d --> ", i); while (p_read != NULL) { printf("V%d(%d)", p_read->adjvex, p_read->weight); p_read = p_read->nextarc; if (p_read != NULL) printf(" --> "); } printf("\n"); } } } void findIndegree(ALGraph alg, int indegree[]) { // Put the ALGraph's vertices indegree into indegree[] int i; for (i = 0; i < alg.vexnum; i++) { indegree[i] = 0; } for (i = 0; i < alg.vexnum; i++) { ArcNode *p_read = alg.vertices[i].firstarc; while (p_read != NULL) { indegree[p_read->adjvex]++; p_read = p_read->nextarc; } } } void TopologicalSort(ALGraph alg) { // Topological sort for ALGraph without weight printf("\nThe most simple topological sort without wight: (Not all sequences)\n"); int i; int count; int indegree[alg.vexnum]; findIndegree(alg, indegree); /*for (i = 0; i < alg.vexnum; i++) { printf("V%d's indegree is %d\n", i, indegree[i]); }*/ // For simulate topological sort, we need a stack. Stack stack; initStack(&stack); for (i = 0; i < alg.vexnum; i++) { if (indegree[i] == 0) push(&stack, i); } count = 0; while (!empty(stack)) { int v = pop(&stack); if (count == 0) printf("V%d", v); else { printf(", V%d", v); } count++; ArcNode *p_read = alg.vertices[v].firstarc; while (p_read != NULL) { if ((--indegree[p_read->adjvex]) == 0) { push(&stack, p_read->adjvex); } p_read = p_read->nextarc; } } printf("\n"); if (count < alg.vexnum) { printf("This ALGraph has loop\n"); } } /* These two functions are used to find criticalpath */ int TopologicalOrder(ALGraph alg, Stack *t, int ve[]) { // Topological sort for ALGraph and calculate the earliest time of vertices int i; int count; int indegree[alg.vexnum]; Stack stack; count = 0; findIndegree(alg, indegree); initStack(&stack); for (i = 0; i < alg.vexnum; i++) { ve[i] = 0; if (indegree[i] == 0) push(&stack, i); } while(!empty(stack)) { int v = pop(&stack); push(t, v); count++; ArcNode *p_read = alg.vertices[v].firstarc; while (p_read != NULL) { int k = p_read->adjvex; if((--indegree[k]) == 0) { push(&stack, k); } if (ve[v] + p_read->weight > ve[k]) { ve[k] = ve[v] + p_read->weight; } p_read = p_read->nextarc; } } if (count < alg.vexnum) { return 0; // This means the ALGraph has loop } return 1; } void findCriticalpath(ALGraph alg) { // Finding critical path using topological and inverse topological sort printf("\nThe critical path:\n"); Stack t; int ve[alg.vexnum]; int vl[alg.vexnum]; int i; initStack(&t); if (TopologicalOrder(alg, &t, ve) == 0) { printf("ERROR! The ALGraph has loop\n"); } for (i = 0; i < alg.vexnum; i++) { vl[i] = ve[alg.vexnum - 1]; } while (!empty(t)) { int v = pop(&t); ArcNode *p_read = alg.vertices[v].firstarc; while (p_read != NULL) { int k = p_read->adjvex; int durt = p_read->weight; if (vl[k] - durt < vl[v]) { vl[v] = vl[k] - durt; } p_read = p_read->nextarc; } } for (i = 0; i < alg.vexnum; i++) { ArcNode *p_read = alg.vertices[i].firstarc; while (p_read != NULL) { int k = p_read->adjvex; int durt = p_read->weight; if (ve[i] == vl[k] - durt) { printf("V%d --%d--> V%d\n", i, durt, k); } p_read = p_read->nextarc; } } } int main() { // Main entry and give a sample printf("为了模拟拓扑排序和关键路径,假设一个项目将会有如下内容:\n"); printf("1\ 项目分为9个事件点(编号V0~8)\n"); printf("2\ 每个事件点之间(从一个事件点到另一个事件点名为活动)估算了时间\n\n"); printf("事件点之间有如下关系:(事件编号 --耗时--> 事件编号)\n"); printf("V0 --6--> V1 && V0 --4--> V2 && V0 --5-->V3\n"); printf("V1 --1--> V4\n"); printf("V2 --1--> V4\n"); printf("V3 --2--> V5\n"); printf("V4 --9--> V6 && V4 --8--> V7\n"); printf("V5 --4--> V7\n"); printf("V6 --2--> V8\n"); printf("V7 --4--> V8\n\n"); ALGraph alg; createALG(&alg, 9, 11); showALG(alg); TopologicalSort(alg); //最简单的拓扑排序,不考虑路径权重 findCriticalpath(alg); //运用拓扑、逆拓扑顺序以及权重找关键路径 printf("\n"); getchar(); return 0; }