news 2026/8/22 10:34:33

【30天从零学Python】重要补充四、检测有向环 - Kahn算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【30天从零学Python】重要补充四、检测有向环 - Kahn算法

30天从零学Python

通信工程专业科班生,用了几十年MATLAB,为了过大厂机考,不得不自学Python。

文章目录

  • 30天从零学Python
  • 重要补充四、检测有向环 - Kahn算法
  • 1. 有向环与拓扑排序
    • 1.1 Kahn 算法核心原理(通俗版)
    • 1.2 Kahn 算法代码实现(适配函数调用场景)
  • 2. 主要坑点
    • 2.1 Kahn 算法坑点
  • 总结

重要补充四、检测有向环 - Kahn算法

本集重点补充用于检测有向环的 Kahn 算法(拓扑排序的经典实现),该算法能高效检测函数调用、任务依赖等场景中是否出现循环依赖(比如 A 调用 B、B 调用 C、C 又调用 A),是大厂机考中高频考点。


1. 有向环与拓扑排序

  • 在函数调用场景中,有向环就是循环调用(比如函数 A 调用 B,B 又调用 A),这种情况会导致栈无限增长。
  • 拓扑排序是对有向无环图(DAG)的节点进行排序,使得所有有向边从排序靠前的节点指向靠后的节点。Kahn 算法通过拓扑排序的过程,能直观检测出图中是否存在环。

1.1 Kahn 算法核心原理(通俗版)

Kahn 算法像 “剥洋葱” 一样处理节点:

  1. 先统计每个节点的入度(有多少个节点指向它,对应 “有多少个函数调用当前函数”);
  2. 把所有 “入度为 0” 的节点(无被调用的起始函数)加入队列;
  3. 不断从队列取出节点,删除该节点的所有出边(即把它指向的节点入度减 1);如果某个节点入度减到 0,就加入队列;
  4. 最终如果处理的节点数 <总节点数,说明存在环(剩下的节点形成闭环,无法被 “剥完”)
    图片说明:
    假设有5个函数,用节点1,2,3,4,5表示,箭头a指向b表示a调用b。
    在这里插入图片描述

1.2 Kahn 算法代码实现(适配函数调用场景)

fromcollectionsimportdequedefhas_cycle(func_calls):""" 检测函数调用关系中是否存在有向环 :param func_calls: 函数调用关系,格式为 {(调用者): [(被调用者, 内存)], ...} :return: (是否有环, 拓扑排序结果) """# 1. 统计所有函数节点all_funcs=set()forcallerinfunc_calls:all_funcs.add(caller)forcallee,_infunc_calls[caller]:all_funcs.add(callee)all_funcs=list(all_funcs)# 2. 初始化入度字典(key:函数,value:入度)in_degree={func:0forfuncinall_funcs}forcallerinfunc_calls:forcallee,_infunc_calls[caller]:in_degree[callee]+=1# 被调用者入度+1# 3. 初始化队列:入度为0的节点(起始函数)queue=deque()forfuncinall_funcs:ifin_degree[func]==0:queue.append(func)# 4. 执行Kahn算法processed=0# 记录处理过的节点数topo_order=[]# 拓扑排序结果whilequeue:current=queue.popleft()topo_order.append(current)processed+=1# 遍历当前节点的所有被调用者,入度减1ifcurrentinfunc_calls:forcallee,_infunc_calls[current]:in_degree[callee]-=1ifin_degree[callee]==0:queue.append(callee)# 5. 判断是否有环:处理节点数 < 总节点数 → 有环has_cycle_flag=processed<len(all_funcs)returnhas_cycle_flag,topo_order# 测试案例1:无环(正常函数调用)if__name__=="__main__":# 案例1:0→1(128),1→2(128)(无环)call_map1={0:[(1,128)],1:[(2,128)]}cycle1,topo1=has_cycle(call_map1)print(f"案例1 - 是否有环:{cycle1},拓扑排序:{topo1}")# 输出:False,[0,1,2]# 案例2:0→1,1→2,2→0(有环)call_map2={0:[(1,100)],1:[(2,200)],2:[(0,300)]}cycle2,topo2=has_cycle(call_map2)print(f"案例2 - 是否有环:{cycle2},拓扑排序:{topo2}")# 输出:True,[](无入度为0的节点)

2. 主要坑点

2.1 Kahn 算法坑点

  1. 统计节点时容易遗漏:必须包含 “调用者” 和 “被调用者” 所有函数,否则会误判环;
  2. 入度初始化要覆盖所有节点:即使是入度为 0 的起始函数,也要初始化入度为 0;
  3. 队列处理时要遍历当前节点的所有出边:避免漏减被调用者的入度。

总结

总结

  1. Kahn 算法是检测有向环的高效方法,核心是 “入度统计 + 队列处理”,适配函数调用循环依赖检测;
  2. 实现 Kahn算法时要确保覆盖所有节点、正确维护入度。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 9:25:50

电科金仓数据库如何支持Oracle风格的PL/SQL操作

引言 在数据库国产化替代的浪潮中,企业面临的最大挑战之一就是如何平滑迁移现有的Oracle应用系统。KingbaseES(简称KES)作为国产数据库的代表产品,通过深度的Oracle兼容性设计,特别是在PL/SQL操作层面的全面支持,为企业提供了一条低成本、低风险的迁移路径。本文将详细介绍Kin…

作者头像 李华
网站建设 2026/8/22 7:16:15

全员 RTO5 政策,TikTok 开卷?

TikTok 开卷&#xff1f; TikTok 虽然和抖音性质类似&#xff0c;母公司也都是字节跳动。 但两者的工作节奏&#xff0c;其实差异挺大&#xff0c;毕竟 TikTok 的主要办公地点&#xff0c;是在美国洛杉矶或新加坡。 一些海外 IT 公司常见的福利待遇&#xff0c;TikTok 还是享受…

作者头像 李华
网站建设 2026/8/22 8:25:20

JSP如何结合AES加密实现大文件上传存储?

文件管理系统毕业设计&#xff1a;从零到崩溃的全过程 1. 我的毕业设计困境 "卧槽&#xff0c;这毕业设计是要我命啊&#xff01;"当我看到老师给出的文件管理系统需求时&#xff0c;差点把刚买的珍珠奶茶喷出来。 10G大文件上传&#xff1f;断点续传&#xff1f;…

作者头像 李华
网站建设 2026/8/22 8:08:28

毕业设计项目 基于机器视觉的目标跟踪算法

文章目录 0 前言2 目标跟踪效果3 目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 0 前言 &#x1f525; 今天学长向大家分享一个毕业设计项目 为了大家能够顺利以及最少的精力通过毕设&…

作者头像 李华
网站建设 2026/8/22 9:33:36

【大模型预训练】15-分布式训练概述:解决单机算力瓶颈的核心技术路径

引言分布式训练是现代深度学习中解决单机算力瓶颈的核心技术路径之一。随着深度学习模型的复杂性和数据量的急剧增加&#xff0c;传统的单机训练方式已难以满足高效计算的需求。分布式训练通过将计算任务分配到多个计算节点上&#xff0c;协同完成模型的训练过程&#xff0c;从…

作者头像 李华
网站建设 2026/8/21 23:15:27

重构智慧书-第10条:名声与好运

一、原文呈现名声与好运一个经久不衰&#xff0c;一个流转不定。前者常跚跚来迟&#xff0c;后者可助人乐生。好运须防他人嫉妒;名声须防湮没无闻。你可以诚心求好运有时亦可努力促成之;然一切名声无不以持之以恒的苦干为本。求名的愿望植根于力量与旺盛的精力。从古到今&#…

作者头像 李华