【数据结构—图】拓扑Topo排序

本文深入探讨了图论中的拓扑排序概念,详细解释了如何对有向无环图(DAG)进行拓扑排序,并提供了相关算法实现的步骤和示例,帮助读者理解这一重要的数据结构操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MaxSize 50

typedef struct ArcNode{
    int adjvex;
    ArcNode *next;
};

struct VNode{
    char value;
    ArcNode *first;
};

struct AdGraph{
    VNode vertices[MaxSize];
    int vexnum,arcnum;
};


//求图中每个顶点的入度
void getAllNodeDegree(AdGraph G,int *indegree){
    for(int i = 0;i < G.vexnum;i++){
        ArcNode *p = G.vexnum[i].first;
        while(p){
            indegree[p->adjvex]++;
            p = p->next;
        }
    }
}


//算法思想:
/**
    首先,先用一个indegree数组把所有顶点的入度都初始化为0,再用一个函数(getAllNodeDegree())来得到整个图中所有顶点的入度。
    遍历整个数组,将入度为0的元素序列保存到栈中(stack[MaxSize]),当栈不为空的时候(top != -1),
将最后一个元素出栈,然后将其发到其他顶点的边也删除(这里的删除是逻辑删除,更改的是indegree[]),直到p走到空,(当p走到空的过程中,可能会有p->adjvex的顶点的入度被删完了,所以如果每一轮while(p){}循环里面都要设置if(indegree[p->adjvex] == 0;),来检测这一轮while循环删除里是否有元素的入度被删为
### 数据结构图论中的拓扑排序 #### 定义与概念 在图论中,对一个有向无环(Directed Acyclic Graph, DAG) G 进行拓扑排序是指将 G 中所有顶点排成一个线性序列,使得中任意一对顶点 u 和 v,如果存在一条从 u 到 v 的边,则 u 在此线性序列中会出现在 v 之前。这种线性序列被称为满足拓扑次序(Topological Order)的序列,即拓扑序列[^3]。 #### 算法实现方式之一:Kahn's Algorithm (基于入度) 一种常见的用于计算拓扑排序的方法是 Kahn 提出的算法,其核心思想在于反复寻找当前中入度为零的节点并移除它们及其发出的所有边直到无法继续为止: ```python from collections import deque, defaultdict def topological_sort_kahn(graph): indegree = {node: 0 for node in graph} # 初始化各结点入度 # 计算每个节点的实际入度数 for nodes in graph.values(): for node in nodes: indegree[node] += 1 queue = deque([node for node in indegree if indegree[node] == 0]) # 所有起始节点加入队列 topo_order = [] while queue: current_node = queue.popleft() topo_order.append(current_node) for neighbor in graph[current_node]: indegree[neighbor] -= 1 if indegree[neighbor] == 0: queue.append(neighbor) if len(topo_order) != len(indegree): # 如果不是所有的节点都被处理过说明存在环路 raise ValueError("Cycle detected") return topo_order ``` 上述代码实现了通过维护一个记录各个节点入度计数值来逐步构建拓扑顺序列表的过程[^2]。 #### 另一常见方法:深度优先搜索DFS 除了基于入度的方式外,还可以利用深度优先遍历来进行拓扑排序,在访问每一个新节点时将其压栈而不是立即输出;当回溯到根节点后再弹出这些被标记过的节点形成最终的结果集。这种方法同样可以有效地找出符合条件的路径而不必担心遇到循环依赖的情况。 ```python def dfs_topological_sort_util(node, visited, stack, adj_list): visited.add(node) for neighbour in adj_list.get(node, []): if neighbour not in visited: dfs_topological_sort_util(neighbour, visited, stack, adj_list) stack.insert(0,node) def topological_sort_dfs(adj_list): visited = set() stack=[] for node in list(adj_list.keys()): if node not in visited: dfs_topological_sort_util(node,visited,stack,adj_list) return stack ``` 这段Python函数展示了如何使用递归形式的DFS执行拓扑排序,并返回按正确顺序排列好的节点数组。 #### 应用场景举例 - **编译器优化**:编译期间的任务调度可以通过分析程序控制流(CFGs)来进行有效的指令重排以减少寄存器压力或提高缓存命中率。 - **项目管理工具甘特绘制**:帮助项目经理安排任务之间的先后关系以及识别潜在的关键路径。 - **课程先修条件规划**:大学选课系统可以根据学科间的前置要求自动生成合理的学习路线建议给学生参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值