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