關鍵路徑 C語言實現
阿新 • • 發佈:2018-10-31
#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");
/*
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--];
}
#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 41 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--];
}