#include<stdio.h>
#include<stdlib.h>
#define MAX 65535
typedef struct Graph
{
char* vexs;//顶点
int** arcs;//边--数组(二级指针)
int vexsnum;
int arcsnum;
}Graph;
typedef struct Node//用栈来存储入度数,方便遍历
{
int data;
struct Node* next;
}Node;
Node* initStack()
{
Node* stack = (Node*)malloc(sizeof(Node));
stack->data = 0;
stack->next = NULL;
return stack;
}
int isEmpty(Node* stack)//判空
{
if (stack->next == NULL)
{
return 1;
}
else
{
return 0;
}
}
void push(Node* stack, int data)//入栈
{
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->next = stack->next;
stack->next = node;
stack->data++;
}
int pop(Node* stack)//出栈
{
if (!isEmpty(stack))
{
Node* node = stack->next;
stack->next = node->next;
return node->data;
}
else
{
return -1;
}
}
int* findInDegrees(Graph* G)//统计入度
{
int* inDegrees = (int*)malloc(sizeof(int) * G->vexsnum);
for (int i = 0; i < G->vexsnum; i++)//初始化
{
inDegrees[i] = 0;
}
for (int i = 0; i < G->vexsnum; i++)//统计以第一个节点为起始点的一列的入度
{
for (int j = 0; j < G->vexsnum; j++)
{
if (G->arcs[i][j]>0 && G->arcs[i][j] != MAX)
{
inDegrees[j] = inDegrees[j] + 1;
}
}
}
return inDegrees;
}
int* topologicalSort(Graph* G)//拓扑排序
{
int index = 0;
int* inDegrees = findInDegrees(G);
int* top = (int*)malloc(sizeof(int) * G->vexsnum);
Node* stack = initStack();
for (int i = 0; i < G->vexsnum; i++)
{
if (inDegrees[i] == 0)//如果入度为0,则入栈
{
push(stack, i);
}
}
while (!isEmpty(stack))//栈不为空,则出栈
{
int vex = pop(stack);
top[index++] = vex;//记录出栈的元素
for (int i = 0; i < G->vexsnum; i++)
{
if (G->arcs[vex][i] && G->arcs[vex][i] != MAX)//如果有边,让边减一
{
inDegrees[i] = inDegrees[i] - 1;
if (inDegrees[i] == 0)//如果减到0,继续入栈
{
push(stack, i);
}
}
}
}
for (int i = 0; i < index; i++)//输出其拓扑排序
{
printf("%c ", G->vexs[top[i]]);
}
printf("\n");
return top;
}
Graph* initGraph(int vexsnum)//图的初始化
{
Graph* G = (Graph*)malloc(sizeof(Graph));//整个图开辟空间
G->vexs = (char*)malloc(sizeof(char) * vexsnum);//顶点开辟空间
G->arcs = (int**)malloc(sizeof(int*) * vexsnum);//边开辟空间
for (int i = 0; i < vexsnum; i++)
{
G->arcs[i] = (int*)malloc(sizeof(int) * vexsnum);//把一个一维数组的每个值的指针指向一个一维数组
}
G->vexsnum = vexsnum;
G->arcsnum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs)//把顶点和边赋值给二维数组
{
for (int i = 0; i < G->vexsnum; i++)
{
G->vexs[i] = vexs[i];
for (int j = 0; j < G->vexsnum; j++)
{
G->arcs[i][j] = *(arcs + i * G->vexsnum + j);
if (G->arcs[i][j] != 0 && G->arcs[i][j] !=MAX)//判断是否右边
{
G->arcsnum++;
}
}
}
}
//深度优先遍历
void DFS(Graph* G, int* visited, int index)//visited看该节点是否被访问,index看访问的那个节点
{
printf("%c ", G->vexs[index]);//先访问该节点
visited[index] = 1;
for (int i = 0; i < G->vexsnum; i++)//找到相连的顶点
{
if (G->arcs[index][i] >0 && G->arcs[index][i] != MAX && !visited[i])//如果未被访问,则递归
{
DFS(G, visited, i);
}
}
}
int getIndex(int* top, Graph* G, int i)//获取图中的index索引值
{
int j = 0;
for (j = 0; j < G->vexsnum; j++)
{
if (top[j] == i)
{
break;
}
}
return j;
}
void criticalPath(Graph* G)//关键路径算法
{
int* top = topologicalSort(G);
int* early = (int*)malloc(sizeof(int) * G->vexsnum);//定义数组存储两个事件
int* late = (int*)malloc(sizeof(int) * G->vexsnum);
for (int i = 0; i < G->vexsnum; i++)//对其进行初始化
{
early[i] = 0;
late[i] = 0;
}
//计算最早发生时间
for (int i = 0; i < G->vexsnum; i++)
{
int max = 0;
for (int j = 0; G->vexsnum; j++)
{
if (G->arcs[j][top[i]] > 0 && G->arcs[j][top[i]] != MAX)
{
int index = getIndex(top, G, j);//获取图中的index索引值
if (early[index] + G->arcs[j][top[i]] > max)//获取最大时间
{
max = early[index] + G->arcs[j][top[i]];
}
}
}
early[i] = max;
}
for (int i = 0; i < G->vexsnum; i++)
{
printf("%d ", early[i]);
}
printf("\n");
//计算最晚发生时间
late[(G->vexsnum) - 1] = early[(G->vexsnum) - 1];
for (int i = (G->vexsnum) - 2; i < G->vexsnum; i--)
{
int min = MAX;
for (int j = 0; j < G->vexsnum; j++)
{
if (G->arcs[top[i]][j] > 0 && G->arcs[top[i]][j] != MAX)
{
int index = getIndex(top, G, j);
if (late[index] - G->arcs[top[i]][j] < min)
{
min = late[index] - G->arcs[top[i]][j];
}
}
}
}
for (int i = 0; i < G->vexsnum; i++)
{
printf("%d ", late[i]);
}
printf("\n");
//计算并打印关键路径
for (int i = 0; i < G->vexsnum; i++)
{
for (int j = 0; j < G->vexsnum; j++)
{
if (G->arcs[i][j] > 0 && G->arcs[i][j] != MAX)
{
int start = getIndex(top, G, i);
int end = getIndex(top, G, j);
if (late[end] - G->arcs[i][j] - early[start] == 0)
{
printf("start= %d end= %d\n", i, j);
}
}
}
}
}
int main()
{
Graph* G = initGraph(9);
int* visited = (int*)malloc(sizeof(int) * G->vexsnum);
for (int i = 0; i < G->vexsnum; i++)
{
visited[i] = 0;
}
int arcs[9][9] = {
0,6,4,5,MAX,MAX,MAX,MAX,MAX,
MAX,0,MAX,MAX,1,MAX,MAX,MAX,MAX,
MAX,MAX,0,MAX,1,MAX,MAX,MAX,MAX,
MAX,MAX,MAX,0,MAX,2,MAX,MAX,MAX,
MAX,MAX,MAX,MAX,0,MAX,9,7,MAX,
MAX,MAX,MAX,MAX,MAX,0,MAX,4,MAX,
MAX,MAX,MAX,MAX,MAX,MAX,0,MAX,2,
MAX,MAX,MAX,MAX,MAX,MAX,MAX,0,4,
MAX,MAX,MAX,MAX,MAX,MAX,MAX,MAX,0
};
createGraph(G, "012345678", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
criticalPath(G);
return 0;
}
C语言实现关键路径的算法
最新推荐文章于 2023-06-29 12:00:00 发布