版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LoverJuan/article/details/78718123
#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 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--];
}
#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 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--];
}