数据结构 C 代码 7.4: 关键路径

摘要: 关键路径算法有一定的难度, 先从左到右, 再从右到左.

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 函数.
  • 逻辑有一点难度, 当然, 也很有趣.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值