C语言代码记忆之拓扑排序与关键路径

#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;
}

你可能感兴趣的:(C语言代码记忆之拓扑排序与关键路径)