摘要: 关键路径算法有一定的难度, 先从左到右, 再从右到左.
1. 代码
将 Java 代码https://blog.csdn.net/minfanphd/article/details/116975772 稍作整理, 告诉 DeepSeek: 将如下 Java 代码翻译为 C 代码.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_DISTANCE 10000
typedef struct IntMatrix {
int **data;
int rows;
int cols;
} IntMatrix;
IntMatrix* IntMatrix_create(int rows, int cols);
IntMatrix* IntMatrix_copy(const IntMatrix* src);
IntMatrix* IntMatrix_identity(int rows);
void IntMatrix_free(IntMatrix* matrix);
void IntMatrix_print(IntMatrix* matrix);
int IntMatrix_add(IntMatrix* self, const IntMatrix* other);
IntMatrix* IntMatrix_multiply(const IntMatrix* a, const IntMatrix* b);
typedef struct Net {
int numNodes;
IntMatrix* weightMatrix;
} Net;
Net* Net_create(int numNodes);
Net* Net_create_from_matrix(int** matrix, int rows, int cols);
void Net_free(Net* net);
bool* criticalPath(Net* net);
// IntMatrix 函数实现
IntMatrix* IntMatrix_create(int rows, int cols) {
IntMatrix* matrix = (IntMatrix*)malloc(sizeof(IntMatrix));
matrix->rows = rows;
matrix->cols = cols;
matrix->data = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix->data[i] = (int*)malloc(cols * sizeof(int));
memset(matrix->data[i], 0, cols * sizeof(int));
}
return matrix;
}
IntMatrix* IntMatrix_copy(const IntMatrix* src) {
IntMatrix* dest = IntMatrix_create(src->rows, src->cols);
for (int i = 0; i < src->rows; i++) {
memcpy(dest->data[i], src->data[i], src->cols * sizeof(int));
}
return dest;
}
IntMatrix* IntMatrix_identity(int rows) {
IntMatrix* matrix = IntMatrix_create(rows, rows);
for (int i = 0; i < rows; i++) {
matrix->data[i][i] = 1;
}
return matrix;
}
void IntMatrix_free(IntMatrix* matrix) {
for (int i = 0; i < matrix->rows; i++) {
free(matrix->data[i]);
}
free(matrix->data);
free(matrix);
}
void IntMatrix_print(IntMatrix* matrix) {
printf("[");
for (int i = 0; i < matrix->rows; i++) {
if (i > 0) printf(" ");
printf("[");
for (int j = 0; j < matrix->cols; j++) {
printf("%d", matrix->data[i][j]);
if (j < matrix->cols - 1) printf(", ");
}
printf("]");
if (i < matrix->rows - 1) printf(",\n");
}
printf("]\n");
}
int IntMatrix_add(IntMatrix* self, const IntMatrix* other) {
if (self->rows != other->rows || self->cols != other->cols) {
fprintf(stderr, "Matrix dimensions mismatch\n");
return -1;
}
for (int i = 0; i < self->rows; i++) {
for (int j = 0; j < self->cols; j++) {
self->data[i][j] += other->data[i][j];
}
}
return 0;
}
IntMatrix* IntMatrix_multiply(const IntMatrix* a, const IntMatrix* b) {
if (a->cols != b->rows) {
fprintf(stderr, "Matrix multiplication dimensions mismatch\n");
return NULL;
}
IntMatrix* result = IntMatrix_create(a->rows, b->cols);
for (int i = 0; i < a->rows; i++) {
for (int j = 0; j < b->cols; j++) {
for (int k = 0; k < a->cols; k++) {
result->data[i][j] += a->data[i][k] * b->data[k][j];
}
}
}
return result;
}
// Net 函数实现
Net* Net_create(int numNodes) {
Net* net = (Net*)malloc(sizeof(Net));
net->numNodes = numNodes;
net->weightMatrix = IntMatrix_create(numNodes, numNodes);
for (int i = 0; i < numNodes; i++) {
for (int j = 0; j < numNodes; j++) {
net->weightMatrix->data[i][j] = MAX_DISTANCE;
}
}
return net;
}
Net* Net_create_from_matrix(int** matrix, int rows, int cols) {
Net* net = (Net*)malloc(sizeof(Net));
net->weightMatrix = IntMatrix_create(rows, cols);
net->numNodes = rows;
for (int i = 0; i < rows; i++) {
memcpy(net->weightMatrix->data[i], matrix[i], cols * sizeof(int));
}
return net;
}
void Net_free(Net* net) {
IntMatrix_free(net->weightMatrix);
free(net);
}
bool* criticalPath(Net* net) {
int numNodes = net->numNodes;
int* tempInDegrees = (int*)calloc(numNodes, sizeof(int));
int* tempEarliestTime = (int*)calloc(numNodes, sizeof(int));
int* tempOutDegrees = (int*)calloc(numNodes, sizeof(int));
int* tempLatestTime = (int*)malloc(numNodes * sizeof(int));
bool* result = (bool*)calloc(numNodes, sizeof(bool));
// 计算入度
for (int i = 0; i < numNodes; i++) {
for (int j = 0; j < numNodes; j++) {
if (net->weightMatrix->data[i][j] != -1) {
tempInDegrees[j]++;
}
}
}
// 拓扑排序计算最早时间
int* inDegreesCopy = (int*)malloc(numNodes * sizeof(int));
memcpy(inDegreesCopy, tempInDegrees, numNodes * sizeof(int));
for (int i = 0; i < numNodes; i++) {
if (inDegreesCopy[i] != 0) continue;
for (int j = 0; j < numNodes; j++) {
if (net->weightMatrix->data[i][j] != -1) {
int newTime = tempEarliestTime[i] + net->weightMatrix->data[i][j];
if (newTime > tempEarliestTime[j]) {
tempEarliestTime[j] = newTime;
}
inDegreesCopy[j]--;
}
}
}
printf("Earliest time: ");
for (int i = 0; i < numNodes; i++) {
printf("%d, ", tempEarliestTime[i]);
}
printf("\n");
// 计算出度
for (int i = 0; i < numNodes; i++) {
for (int j = 0; j < numNodes; j++) {
if (net->weightMatrix->data[i][j] != -1) {
tempOutDegrees[i]++;
}
}
}
// 初始化最晚时间
int criticalTime = tempEarliestTime[numNodes - 1];
for (int i = 0; i < numNodes; i++) {
tempLatestTime[i] = criticalTime;
}
// 反向拓扑排序计算最晚时间
int* outDegreesCopy = (int*)malloc(numNodes * sizeof(int));
memcpy(outDegreesCopy, tempOutDegrees, numNodes * sizeof(int));
for (int i = numNodes - 1; i >= 0; i--) {
if (outDegreesCopy[i] != 0) continue;
for (int j = 0; j < numNodes; j++) {
if (net->weightMatrix->data[j][i] != -1) {
int newTime = tempLatestTime[i] - net->weightMatrix->data[j][i];
if (newTime < tempLatestTime[j]) {
tempLatestTime[j] = newTime;
}
outDegreesCopy[j]--;
}
}
}
printf("Latest time: ");
for (int i = 0; i < numNodes; i++) {
printf("%d, ", tempLatestTime[i]);
}
printf("\n");
// 确定关键路径
for (int i = 0; i < numNodes; i++) {
result[i] = (tempEarliestTime[i] == tempLatestTime[i]);
}
free(tempInDegrees);
free(tempEarliestTime);
free(tempOutDegrees);
free(tempLatestTime);
free(inDegreesCopy);
free(outDegreesCopy);
return result;
}
// 测试代码
int main() {
int tempMatrix3[6][6] = {
{ -1, 3, 2, -1, -1, -1 },
{ -1, -1, -1, 2, 3, -1 },
{ -1, -1, -1, 4, -1, 3 },
{ -1, -1, -1, -1, -1, 2 },
{ -1, -1, -1, -1, -1, 1 },
{ -1, -1, -1, -1, -1, -1 }
};
// 转换为二维指针数组
int** matrix = (int**)malloc(6 * sizeof(int*));
for (int i = 0; i < 6; i++) {
matrix[i] = (int*)malloc(6 * sizeof(int));
memcpy(matrix[i], tempMatrix3[i], 6 * sizeof(int));
}
Net* net = Net_create_from_matrix(matrix, 6, 6);
bool* critical = criticalPath(net);
printf("Critical nodes: ");
for (int i = 0; i < 6; i++) {
if (critical[i]) printf("%d ", i);
}
printf("\n");
// 释放内存
for (int i = 0; i < 6; i++) free(matrix[i]);
free(matrix);
Net_free(net);
free(critical);
return 0;
}
2. 运行结果
Earliest time: 0, 3, 2, 6, 6, 8,
Latest time: 0, 4, 2, 6, 7, 8,
Critical nodes: 0 2 3 5
3. 小结
- 主要看 criticalPath 函数.
- 逻辑有一点难度, 当然, 也很有趣.