1. 程式人生 > >關鍵路徑 C語言實現

關鍵路徑 C語言實現

#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 50
#define false 0
#define true 1
typedef int bool;
typedef int Vertex;
typedef int WeightType;
struct VertexNode;//頂點結構
struct AdjNode;//鄰接頂點結構
typedef struct AdjNode *PtrToAdjVertexNode;//指向鄰接點的指標
typedef struct GraphNode *PtrToGraphNode;//指向圖的指標
typedef PtrToGraphNode ListGraph;
typedef struct EdgeNode *Edge;
typedef struct VertexNode
{
    PtrToAdjVertexNode Head;//指向第一個鄰接點的指標
} AdjList[MaxVertexNum];
struct AdjNode
{
    Vertex AdjVertex;//鄰接點下標
    WeightType Weight;//權重
    PtrToAdjVertexNode Next;
};
struct GraphNode
{
    int VertexNum;
    int EdgeNum;
    AdjList G;
};
/*將邊的資訊封裝,V1到V2權重為Weight的邊*/
struct EdgeNode
{
    Vertex V1;
    Vertex V2;
    WeightType Weight;
};
/*Stack ADT*/
typedef Vertex ElementType;
typedef struct StackNode *Stack;
struct StackNode
{
    ElementType *Array;
    int Capacity;
    int Top;
};
int IsEmptyStack(Stack S);
int IsFullStack(Stack S);
Stack CreatStack(int Capacity);
int Push(ElementType X, Stack S);
ElementType Pop(Stack S);
/*Stack END*/
ListGraph CreatGraph(int VertexNum);
void InsertEdge(ListGraph Graph, Edge E);
Edge ReadEdge(void);//輸入函式
int* GetInDegree(ListGraph Graph);
int TopologicalOrder(ListGraph Graph, Stack T, int *VertexEarlyTime);//用於關鍵路徑的拓撲排序,傳入最早開工時間
int main()
{
    int VertexNum;
    Edge E = NULL;
    printf("輸入頂點數:\n");
    scanf("%d",&VertexNum);
    ListGraph Graph = CreatGraph(VertexNum);
    printf("輸入邊(-1結束),格式:頂點1 頂點2 邊權重\n");
    /*

     9個頂點測試資料

1 2 6

1 3 4
1 4 5
2 5 1
3 5 1
4 6 2
5 7 9
5 8 7
6 8 4
7 9 2
8 9 4
-1
     */
    while((E = ReadEdge()) != NULL)
    {
        InsertEdge(Graph,E);
    }
    CriticalPath(Graph);
    return 0;
}
ListGraph CreatGraph(int VertexNum)
{
    Vertex V;
    ListGraph Graph;
    Graph = (ListGraph)malloc(sizeof(struct GraphNode));
    Graph->VertexNum = VertexNum;
    Graph->EdgeNum = 0;
    for (V = 0; V < Graph->VertexNum; V++) {
        Graph->G[V].Head = NULL;
    }
    return Graph;
}
void InsertEdge(ListGraph Graph, Edge E)
{
    PtrToAdjVertexNode NewNode;
    NewNode = (PtrToAdjVertexNode)malloc(sizeof(struct AdjNode));
    NewNode->AdjVertex = E->V2;
    NewNode->Weight = E->Weight;
    /*將新新增的鄰接點插在鄰接表頭*/
    NewNode->Next = Graph->G[E->V1].Head;
    Graph->G[E->V1].Head = NewNode;
}
Edge ReadEdge(void)
{
    Edge E = (Edge)malloc(sizeof(struct EdgeNode));
    scanf("%d",&E->V1);
    if (E->V1 != -1)
    {
        scanf("%d %d",&E->V2,&E->Weight);
    }else
    {
        E = NULL;
    }
    return E;
}
int* GetInDegree(ListGraph Graph)
{
    int i = 0;
    PtrToAdjVertexNode TempHead;
    int *Array = malloc(sizeof(int)*(Graph->VertexNum+1));
    for (i=1; i<=Graph->VertexNum; i++) {
        Array[i] = 0;
    }
    for (i=1; i<=Graph->VertexNum; i++) {
        TempHead = Graph->G[i].Head;
        while (TempHead) {
            Array[TempHead->AdjVertex]++;
            TempHead = TempHead->Next;
        }
    }
    return Array;
}
int TopologicalOrder(ListGraph Graph, Stack T, int *VertexEarlyTime)
{
    int *InDegreeArray = GetInDegree(Graph);
    Stack S = CreatStack(Graph->VertexNum);
    Vertex i,j,k;
    int count = 0;
    PtrToAdjVertexNode P = NULL;
    //建零入度棧
    for (i = 1; i<=Graph->VertexNum; i++) {
        if (InDegreeArray[i] == 0) {
            Push(i, S);
        }
    }
    while (!IsEmptyStack(S)) {
        j = Pop(S);
        Push(j, T);
        count++;
        for (P = Graph->G[j].Head; P; P = P->Next) {
            k = P->AdjVertex;
            InDegreeArray[k]--;
            if (InDegreeArray[k] == 0) {
                Push(k, S);
            }
            if (VertexEarlyTime[j] + P->Weight > VertexEarlyTime[k]) {
                VertexEarlyTime[k] = VertexEarlyTime[j] + P->Weight;
            }
        }
    }
    printf("拓撲排序結果:\n");
    if (IsEmptyStack(T))
    {
        printf("Empty! Top = %d\n",T->Top);
    }
    for (i = 0; i <= T->Top; ++i)
    {
        printf("%d ", T->Array[i]);
    }
    printf("\n");
    if (count < Graph->VertexNum) {
        return false;
    }else
    {
        return true;
    }
}
int CriticalPath(ListGraph Graph)
{
    Vertex i,j,k;
    PtrToAdjVertexNode P;
    Stack T = CreatStack(Graph->VertexNum);
    int *VertexEarlyTime = malloc(sizeof(WeightType)*(Graph->VertexNum+1));
    int *VertexLastTime = malloc(sizeof(WeightType)*(Graph->VertexNum+1));
    char TAG;
    for (i=1; i<=Graph->VertexNum; i++) {
        VertexEarlyTime[i] = 0;
    }
    if (!TopologicalOrder(Graph, T ,VertexEarlyTime)) {
        return false;
    }
    for (i=1; i<=Graph->VertexNum; i++) {
        VertexLastTime[i] = VertexEarlyTime[i];
    }
    while (!IsEmptyStack(T)) {
        for (j = Pop(T),P = Graph->G[j].Head; P; P = P->Next) {
            k = P->AdjVertex;
            if (VertexLastTime[k]- (P->Weight) < VertexLastTime[j]) {
                VertexLastTime[j] = VertexLastTime[k] - (P->Weight);
            }
        }
    }
    printf("關鍵活動: \n");
    for (j = 0; j<=Graph->VertexNum; j++) {
        for (P = Graph->G[j].Head; P; P = P->Next) {
            k = P->AdjVertex;
            TAG = (VertexEarlyTime[j] == VertexLastTime[k]-P->Weight) ? '*' : ' ';
            printf("%d %d %d %d %d %c\n",j, k, P->Weight, VertexEarlyTime[j],VertexLastTime[k]-P->Weight, TAG);
        }
    }
    return true;
}
/*Stack*/
int IsEmptyStack(Stack S)
{
    return S->Top == -1;
}
int IsFullStack(Stack S)
{
    return S->Top == S->Capacity-1;
}
Stack CreatStack(int Capacity)
{
    Stack S = malloc(sizeof(struct StackNode));
    S->Array = malloc(sizeof(ElementType)*Capacity);
    S->Capacity = Capacity;
    S->Top = -1;
    return S;
}
int Push(ElementType X, Stack S)
{
    if (IsFullStack(S)) {
        return false;
    }
    S->Top++;
    S->Array[S->Top] = X;
    return true;
}
ElementType Pop(Stack S)
{
    if (IsEmptyStack(S)) {
        return false;
    }
    return S->Array[S->Top--];
}