c语言,完整程序,编程实现有向无环图的拓扑排序,使用邻接表存储方式。在图的基本操作基础上添加求顶点的入度、再利用栈操作进行拓扑排序,再求此图的关键路径
时间: 2024-12-18 22:27:57 浏览: 10
在C语言中,我们可以使用邻接表来存储有向无环图(DAG),这是一种常见的图数据结构,其中每个节点有一系列指向其他节点的边。以下是使用邻接表实现有向无环图的拓扑排序、计算顶点入度以及找到关键路径的一个简单示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stack>
// 定义邻接列表结构
typedef struct Node {
int data;
struct Node* next;
} Node;
// 创建新节点
Node* create_node(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 添加边到邻接表
void add_edge(Node** head, int src, int dest) {
Node* newNode = create_node(dest);
newNode->next = (*head)[src];
(*head)[src] = newNode;
}
// 计算节点的入度
int get_indegree(Node** adj_list, int num_nodes) {
for (int i = 0; i < num_nodes; i++) {
(*adj_list)[i]->inDegree = 0;
}
for (int i = 0; i < num_nodes; i++) {
Node* node = (*adj_list)[i];
while (node != NULL) {
node->inDegree++;
node = node->next;
}
}
return 0;
}
// 拓扑排序
bool topological_sort(Node** adj_list, int num_nodes, int* result, int* indegree_count) {
stack<int> s;
bool visited[num_nodes] = {false};
// 初始化入度计数
*indegree_count = get_indegree(adj_list, num_nodes);
// 遍历所有节点,将入度为0的节点压入栈
for (int i = 0; i < num_nodes; i++) {
if (!visited[i] && (*indegree_count)[i] == 0) {
s.push(i);
}
}
while (!s.empty()) {
int node = s.top();
s.pop();
result[node] = node;
visited[node] = true;
Node* curr = (*adj_list)[node];
while (curr != NULL) {
(*indegree_count)[curr->data]--;
if ((*indegree_count)[curr->data] == 0) {
s.push(curr->data);
}
curr = curr->next;
}
}
// 如果所有节点都访问过了,并且结果数组已填满,则表示有解
for (int i = 0; i < num_nodes; i++) {
if (!visited[i]) {
return false;
}
}
return true;
}
// 主函数
int main() {
int num_nodes = 5; // 假设有5个节点
Node** adj_list = new Node*[num_nodes]; // 初始化邻接表
// 填充邻接表...(此处省略实际添加边的操作)
int* topo_order = (int*)malloc(sizeof(int) * num_nodes); // 存储拓扑排序的结果
int indegree_count[num_nodes]; // 存储节点的入度
// 检查并打印拓扑排序
if (topological_sort(adj_list, num_nodes, topo_order, indegree_count)) {
printf("拓扑排序结果: ");
for (int i = 0; i < num_nodes; i++) {
printf("%d ", topo_order[i]);
}
printf("\n");
} else {
printf("无法进行拓扑排序,存在环。\n");
}
// 关键路径的查找(简化版,假设只有一个源节点)
int source = 0; // 设定源节点
int min_time[num_nodes] = {INT_MAX}; // 存储从源到每个节点的最短时间
int key_path[] = {}; // 存储关键路径
// 对于每个节点,更新其最小时间,并找到关键路径
for (int i = 0; i < num_nodes; i++) {
if (min_time[source] + 1 < min_time[i]) {
min_time[i] = min_time[source] + 1;
key_path[0] = source;
key_path[1] = i;
}
}
// 打印关键路径
if (min_time[source] != INT_MAX) {
printf("关键路径: ");
for (int i = 1; i < num_nodes && key_path[i] != -1; i++) {
printf("%d -> %d ", key_path[i - 1], key_path[i]);
}
printf("\n");
} else {
printf("不存在关键路径。\n");
}
free(topo_order);
delete[] adj_list;
return 0;
}
阅读全文