图的拓扑排序是一种线性排序,适用于有向无环图(DAG)。如果图中存在有向环,则无法进行拓扑排序。我们可以使用 Kahn 算法或深度优先搜索(DFS)来实现拓扑排序,并检测有向环。
以下是使用 Kahn 算法和 DFS 的两种实现方式:
方法 1:Kahn 算法
Kahn 算法通过维护一个入度为零的节点队列来逐步生成拓扑排序。如果在处理过程中无法将所有节点排序,则说明存在环。
pythonCopy Codefrom collections import deque, defaultdictdef topological_sort_kahn(graph): # 计算每个节点的入度
in_degree = defaultdict(int) for node in graph: for neighbor in graph[node]:
in_degree[neighbor] += 1
# 初始化队列,将所有入度为零的节点加入队列
queue = deque([node for node in graph if in_degree[node] == 0])
topological_order = [] while queue:
current = queue.popleft()
topological_order.append(current) # 遍历当前节点的邻居,减少其入度
for neighbor in graph[current]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor) # 如果拓扑排序中的节点数不等于图中的节点数,说明存在环
if len(topological_order) != len(graph): return None # 存在环
return topological_order# 示例图(无环)graph = { 'A': ['C'], 'B': ['C', 'D'], 'C': ['E'], 'D': ['F'], 'E': ['H'], 'F': ['G'], 'G': [], 'H': []
}print(topological_sort_kahn(graph)) # 输出: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] 或其他合法顺序# 示例图(有环)cyclic_graph = { 'A': ['B'], 'B': ['C'], 'C': ['A']
}print(topological_sort_kahn(cyclic_graph)) # 输出: None
方法 2:深度优先搜索(DFS)
DFS 方法通过递归访问节点,并在回溯时构建拓扑排序。如果在访问过程中遇到一个正在访问的节点,则说明存在环。
pythonCopy Codedef topological_sort_dfs(graph):
visited = {'visiting': set(), 'visited': set()}
topological_order = []
has_cycle = False
def dfs(node): nonlocal has_cycle if has_cycle: return
if node in visited['visiting']:
has_cycle = True
return
if node in visited['visited']: return
visited['visiting'].add(node) for neighbor in graph.get(node, []):
dfs(neighbor)
visited['visiting'].remove(node)
visited['visited'].add(node)
topological_order.append(node) for node in graph: if node not in visited['visited']:
dfs(node) if has_cycle: return None # 存在环
topological_order.reverse() # 因为是后序添加,需要反转
return topological_order# 示例图(无环)print(topological_sort_dfs(graph)) # 输出: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] 或其他合法顺序# 示例图(有环)print(topological_sort_dfs(cyclic_graph)) # 输出: None
解释:
- Kahn 算法:通过维护入度为零的节点队列来逐步生成拓扑排序。
- DFS 方法:通过递归访问节点,利用标记集合来检测环。
这两种方法都能有效地进行拓扑排序并检测有向环。选择哪种方法取决于具体需求和偏好。
http://www.zgjzs.org
http://www.shangpin.org
http://www.snjrw.org
http://wangluo.zgjzs.org
http://zhineng.zgjzs.org
http://gaosu.zgjzs.org
http://anquan.zgjzs.org
http://wangzhan.zgjzs.org
http://jiaoyu.zgjzs.org
http://guanggao.zgjzs.org
http://shuju.zgjzs.org
http://zhifu.zgjzs.org
http://yingyong.zgjzs.org
http://yonghu.zgjzs.org
http://houtai.zgjzs.org
http://fenxi.zgjzs.org
http://jiekou.zgjzs.org
http://fenxiang.zgjzs.org
http://neirong.zgjzs.org
http://zhuce.zgjzs.org
http://tongji.zgjzs.org
http://ditu.zgjzs.org
http://tuisong.zgjzs.org
http://gouwu.zgjzs.org
http://tuiguang.zgjzs.org
http://shejiao.zgjzs.org
http://zhongguo.zgjzs.org
http://wangguan.zgjzs.org
http://yule.zgjzs.org
http://pingtai.zgjzs.org
http://jichu.zgjzs.org
http://wangjie.zgjzs.org
http://zhishi.zgjzs.org
http://shangcheng.zgjzs.org
http://dianzi.zgjzs.org
http://yinyue.zgjzs.org
http://tupian.zgjzs.org
http://shipin.zgjzs.org
http://wuliu.zgjzs.org
http://gongju.zgjzs.org
http://anquan.zgjzs.org
http://sousuo.zgjzs.org
http://mima.zgjzs.org
http://jiankong.zgjzs.org
http://ceshi.zgjzs.org
http://wangyou.zgjzs.org
http://zixun.zgjzs.org
http://chajian.zgjzs.org
http://kuaidi.zgjzs.org
http://liuliang.zgjzs.org
http://zhengce.zgjzs.org
http://peizhi.zgjzs.org
http://baocun.zgjzs.org
http://yonghu.shangpin.org
http://houtai.shangpin.org
http://pingtai.shangpin.org
http://wangzhan.shangpin.org
http://zhifu.shangpin.org
http://guanggao.shangpin.org
http://yinyue.shangpin.org
http://zixun.shangpin.org
http://shejiao.shangpin.org
http://tuisong.shangpin.org
http://wangguan.shangpin.org
http://zhineng.shangpin.org
http://wangluo.shangpin.org
http://anquan.shangpin.org
http://zhongguo.shangpin.org
http://shuju.shangpin.org
http://jiekou.shangpin.org
http://zhishi.shangpin.org
http://gongneng.shangpin.org
http://tongji.shangpin.org
http://shipin.shangpin.org
http://jiaoyu.shangpin.org
http://ditu.shangpin.org
http://dianzi.shangpin.org
http://mima.shangpin.org
http://liuliang.shangpin.org
http://gouwu.shangpin.org
http://zhengce.shangpin.org
http://yule.shangpin.org
http://baocun.shangpin.org
http://jichu.shangpin.org
http://fenxi.shangpin.org
http://fenxiang.shangpin.org
http://shangcheng.shangpin.org
http://kuaidi.shangpin.org
http://peizhi.shangpin.org
http://wuliu.shangpin.org
http://ceshi.shangpin.org
http://tupian.shangpin.org
http://wangyou.shangpin.org
http://chajian.shangpin.org
http://tuiguang.shangpin.org
http://yingyong.shangpin.org
http://zhuce.shangpin.org
http://sousuo.shangpin.org
http://jiankong.shangpin.org
http://neirong.shangpin.org
http://gongju.shangpin.org
http://zonghe.shangpin.org
http://zhifu.snjrw.org
http://houtai.snjrw.org
http://yule.snjrw.org
http://wangluo.snjrw.org
http://guanggao.snjrw.org
http://shuju.snjrw.org
http://pingtai.snjrw.org
http://ditu.snjrw.org
http://wangzhan.snjrw.org
http://shejiao.snjrw.org
http://jiekou.snjrw.org
http://zhishi.snjrw.org
http://zhineng.snjrw.org
http://jiaoyu.snjrw.org
http://zhongguo.snjrw.org
http://yinyue.snjrw.org
http://yonghu.snjrw.org
http://tuiguang.snjrw.org
http://gouwu.snjrw.org
http://baocun.snjrw.org
http://fenxiang.snjrw.org
http://fenxi.snjrw.org
http://gongneng.snjrw.org
http://wangguan.snjrw.org
http://zixun.snjrw.org
http://dianzi.snjrw.org
http://tupian.snjrw.org
http://wangyou.snjrw.org
http://chajian.snjrw.org
http://wuliu.snjrw.org
http://mima.snjrw.org
http://liuliang.snjrw.org
http://zhuce.snjrw.org
http://zhengce.snjrw.org
http://peizhi.snjrw.org
http://shipin.snjrw.org
http://jichu.snjrw.org
http://tongji.snjrw.org
http://kuaidi.snjrw.org
http://yingyong.snjrw.org
http://sousuo.snjrw.org
http://jiankong.snjrw.org
http://neirong.snjrw.org
http://gongju.snjrw.org
http://tuisong.snjrw.org
http://shangcheng.snjrw.org
http://anli.snjrw.org
http://dianhua.snjrw.org
http://fuwu.snjrw.org