让Ai写个拓扑排序C#算法

news/2025/2/22 7:22:58/文章来源:https://www.cnblogs.com/youlicc/p/18728002

前言

  使用AI的一个有趣例子

  有个业务,在实现过程中需要使用拓扑算法,但我以前所学的东西都还给老师了,刚好这几天公司开展了使用AI的培训与分享,遂想了下,那就让AI来搞下吧。

源代码

  Learning-Case/TopologyAlgorithm at main · qiqiqiyaya/Learning-Case

出场AI工具

  豆包

  DeepSeek

过程

  首先使用的豆包(DeepSeek:服务器繁忙,请稍后再试。)。

  我问:C# 例: A对象依赖B对象的结果,B对象依赖C对象的结果... 该如何排序有序执行。

  豆包回答:

    方法一:使用同步方法按顺序调用(和 使用异步方法按顺序调用,调用方式一样)

        C c = new C();B b = new B(c);A a = new A(b);

  我想,应该是我问的太简单了,遂修改后问:在上述情况中,A对象不直接依赖B,且B对象不直接依赖C对象 。 该如何排序有序执行

  豆包回答:

        // 创建对象实例C c = new C();B b = new B();A a = new A();// 按 C -> B -> A 的顺序执行int cResult = c.GetResult();int bResult = b.GetResult(cResult);int finalResult = a.GetResult(bResult);

  这不是我要的答案,看来还是要直接说出我的直接目的,我问:上述对象依赖关系是拓扑结构,该如何排序有序执行

  豆包回答:如下图

  

  使用 Kahn 算法来实现拓扑排序,使用深度优先搜索进行拓扑排序并执行对象操作,如下代码块

使用深度优先搜索进行拓扑排序并执行对象操作
 using System;
using System.Collections.Generic;// 定义对象类
class MyObject
{public int Id { get; }public Func<int> Action { get; }public MyObject(int id, Func<int> action){Id = id;Action = action;}
}class TopologicalSorter
{// 深度优先搜索辅助方法private static void DFS(int node, Dictionary<int, List<int>> graph, bool[] visited, Stack<int> stack){visited[node] = true;if (graph.ContainsKey(node)){foreach (var neighbor in graph[node]){if (!visited[neighbor]){DFS(neighbor, graph, visited, stack);}}}stack.Push(node);}// 使用深度优先搜索进行拓扑排序并执行对象操作public static List<int> SortAndExecute(List<MyObject> objects, Dictionary<int, List<int>> dependencies){int n = objects.Count;bool[] visited = new bool[n + 1];Stack<int> stack = new Stack<int>();Dictionary<int, MyObject> objectMap = new Dictionary<int, MyObject>();foreach (var obj in objects){objectMap[obj.Id] = obj;}// 对每个未访问的节点进行 DFSfor (int i = 1; i <= n; i++){if (!visited[i]){DFS(i, dependencies, visited, stack);}}List<int> result = new List<int>();while (stack.Count > 0){int currentId = stack.Pop();MyObject currentObj = objectMap[currentId];int output = currentObj.Action();result.Add(output);}return result;}
}class Program
{static void Main(){// 创建对象MyObject objC = new MyObject(3, () =>{Console.WriteLine("C 对象正在执行操作...");return 3;});MyObject objB = new MyObject(2, () =>{Console.WriteLine("B 对象正在执行操作...");return 2;});MyObject objA = new MyObject(1, () =>{Console.WriteLine("A 对象正在执行操作...");return 1;});List<MyObject> objects = new List<MyObject> { objA, objB, objC };// 定义依赖关系,键为依赖对象,值为被依赖对象列表Dictionary<int, List<int>> dependencies = new Dictionary<int, List<int>>{{ 1, new List<int> { 2, 3 } }, // A 依赖 B 和 C{ 2, new List<int> { 3 } }    // B 依赖 C};// 执行拓扑排序并按顺序执行对象操作List<int> results = TopologicalSorter.SortAndExecute(objects, dependencies);Console.WriteLine("最终执行结果:");foreach (var result in results){Console.WriteLine(result);}}
}

   将代码Copy至VS中调试,代码运行完全没问题(我想:这该不会是从哪里Copy来的吧?)。但是实际开发相关业务中可能会出现循环依赖,若出现,我想知道整个循环依赖的信息。

所以我写了个错误的依赖关系,经测试后发现,算法发现循环依赖,但错误如下图,这个错误太抽象了,要是回溯找错误,要吐血。

  

  于是我接着问:结合上下文,上述 Kahn 算法能检测环但不知道具体环相关的信息,抛出异常时附带上环的具体信息

  豆包:如下图

  

  源代码在DouBao-3文件夹下,copy代码放入vs中测试,循环依赖到时发现,但还是无法给出循环依赖时的具体信息。

  我接着问:上一个回答中 FindCycle 函数你帮我测试下,好像有错误

  豆包回答:如下图

  

  源代码在DouBao-4文件夹下copy代码放入vs中测试,循环依赖到时发现,但还是无法给出循环依赖时的具体信息。我很怀疑这个算法是从哪里copy来的,豆包AI推理不出错误

  然后我又问:上一个回答中代码执行后,无法得出环,请重新给出答案

  豆包回答:如下图

  

  

修正后的代码,还是有错误
 using System;
using System.Collections.Generic;// 定义对象类
class MyObject
{public int Id { get; }public string Name { get; }public Func<int> Action { get; }public MyObject(int id, string name, Func<int> action){Id = id;Name = name;Action = action;}public override string ToString(){return $"Object {Name} (ID: {Id})";}
}class TopologicalSorter
{public static List<int> SortAndExecute(List<MyObject> objects, Dictionary<int, List<int>> dependencies){// 存储每个对象的入度var inDegree = new Dictionary<int, int>();foreach (var obj in objects){inDegree[obj.Id] = 0;}// 计算每个对象的入度foreach (var dep in dependencies){foreach (var dependentId in dep.Value){inDegree[dependentId]++;}}// 存储入度为 0 的对象的队列var queue = new Queue<int>();foreach (var obj in objects){if (inDegree[obj.Id] == 0){queue.Enqueue(obj.Id);}}var result = new List<int>();var sortedOrder = new List<int>();// 记录每个节点的父节点,用于回溯环var parentMap = new Dictionary<int, int>();while (queue.Count > 0){int currentId = queue.Dequeue();sortedOrder.Add(currentId);// 找到当前对象MyObject currentObj = objects.Find(obj => obj.Id == currentId);if (currentObj != null){Console.WriteLine($"Executing {currentObj}");// 执行当前对象的操作int output = currentObj.Action();result.Add(output);// 检查当前对象的依赖对象if (dependencies.ContainsKey(currentId)){foreach (var dependentId in dependencies[currentId]){// 记录父节点parentMap[dependentId] = currentId;// 减少依赖对象的入度inDegree[dependentId]--;if (inDegree[dependentId] == 0){queue.Enqueue(dependentId);}}}}}// 检查是否存在环if (sortedOrder.Count != objects.Count){var remainingNodes = new List<int>();foreach (var obj in objects){if (!sortedOrder.Contains(obj.Id)){remainingNodes.Add(obj.Id);}}// 找出一个环var cycle = FindCycle(remainingNodes, parentMap);var cycleInfo = string.Join(" -> ", cycle);throw new InvalidOperationException($"依赖关系中存在环,环的节点顺序为: {cycleInfo}");}return result;}private static List<int> FindCycle(List<int> remainingNodes, Dictionary<int, int> parentMap){foreach (int startNode in remainingNodes){HashSet<int> visited = new HashSet<int>();List<int> path = new List<int>();int current = startNode;while (true){if (visited.Contains(current)){int cycleStartIndex = path.IndexOf(current);List<int> cycle = path.GetRange(cycleStartIndex, path.Count - cycleStartIndex);cycle.Add(current);return cycle;}visited.Add(current);path.Add(current);if (parentMap.ContainsKey(current)){current = parentMap[current];}else{break;}}}return new List<int>();}
}class Program
{static void Main(){// 创建多个对象var objA = new MyObject(1, "A", () =>{Console.WriteLine("A 对象正在执行操作...");return 1;});var objB = new MyObject(2, "B", () =>{Console.WriteLine("B 对象正在执行操作...");return 2;});var objC = new MyObject(3, "C", () =>{Console.WriteLine("C 对象正在执行操作...");return 3;});var objD = new MyObject(4, "D", () =>{Console.WriteLine("D 对象正在执行操作...");return 4;});var objE = new MyObject(5, "E", () =>{Console.WriteLine("E 对象正在执行操作...");return 5;});var objF = new MyObject(6, "F", () =>{Console.WriteLine("F 对象正在执行操作...");return 6;});var objects = new List<MyObject> { objA, objB, objC, objD, objE, objF };// 定义包含环的依赖关系var dependencies = new Dictionary<int, List<int>>{{ 1, new List<int> { 2 } }, // A 依赖 B{ 2, new List<int> { 3 } }, // B 依赖 C{ 3, new List<int> { 1 } }, // C 依赖 A,形成环{ 4, new List<int> { 5 } }, // D 依赖 E{ 5, new List<int> { 6 } }  // E 依赖 F};try{// 执行拓扑排序并按顺序执行对象操作var results = TopologicalSorter.SortAndExecute(objects, dependencies);Console.WriteLine("最终执行结果:");foreach (var result in results){Console.WriteLine(result);}}catch (InvalidOperationException ex){Console.WriteLine(ex.Message);}}
}

  此时我想,估计豆包也给不出什么能够解决的方案了,换DeepSeek试下

  我直接将豆包给的算法Copy给DeepSeek。

  DeepSeek R1思考了好大一串,这里就不展示了,最后给出了算法,DeepSeek使用深度优先搜索(DFS)来检测环,代码如下:

使用深度优先搜索(DFS)来检测环
 using System;
using System.Collections.Generic;
using System.Linq;class MyObject
{public int Id { get; }public string Name { get; }public Func<int> Action { get; }public MyObject(int id, string name, Func<int> action){Id = id;Name = name;Action = action;}public override string ToString(){return $"Object {Name} (ID: {Id})";}
}class TopologicalSorter
{public static List<int> SortAndExecute(List<MyObject> objects, Dictionary<int, List<int>> dependencies){// 构建后继列表和初始化入度var successors = new Dictionary<int, List<int>>();var inDegree = new Dictionary<int, int>();foreach (var obj in objects){inDegree[obj.Id] = 0;successors[obj.Id] = new List<int>();}foreach (var dep in dependencies){int node = dep.Key;foreach (var dependency in dep.Value){successors[dependency].Add(node);inDegree[node]++;}}var queue = new Queue<int>();foreach (var obj in objects){if (inDegree[obj.Id] == 0){queue.Enqueue(obj.Id);}}var result = new List<int>();var sortedOrder = new List<int>();var parentMap = new Dictionary<int, int>();while (queue.Count > 0){int currentId = queue.Dequeue();sortedOrder.Add(currentId);MyObject currentObj = objects.Find(obj => obj.Id == currentId);if (currentObj != null){Console.WriteLine($"Executing {currentObj}");int output = currentObj.Action();result.Add(output);foreach (var successor in successors[currentId]){parentMap[successor] = currentId;inDegree[successor]--;if (inDegree[successor] == 0){queue.Enqueue(successor);}}}}if (sortedOrder.Count != objects.Count){var remainingNodes = objects.Select(obj => obj.Id).Except(sortedOrder).ToList();var cycle = FindCycle(remainingNodes, dependencies);var cycleInfo = string.Join(" -> ", cycle);throw new InvalidOperationException($"依赖关系中存在环,环的节点顺序为: {cycleInfo}");}return result;}private static List<int> FindCycle(List<int> remainingNodes, Dictionary<int, List<int>> dependencies){var visited = new Dictionary<int, VisitState>();var path = new List<int>();foreach (var node in remainingNodes){if (DFS(node, dependencies, visited, path)){// 提取环int cycleStart = path.LastIndexOf(path[path.Count - 1]);return path.Skip(cycleStart).ToList();}}return new List<int>(); // 未找到环,理论上不会发生}private enum VisitState{NotVisited,Visiting,Visited};private static bool DFS(int node, Dictionary<int, List<int>> dependencies, Dictionary<int, VisitState> visited, List<int> path){if (!visited.ContainsKey(node))visited[node] = VisitState.NotVisited;if (visited[node] == VisitState.Visiting){path.Add(node);return true;}if (visited[node] == VisitState.Visited)return false;visited[node] = VisitState.Visiting;path.Add(node);if (dependencies.ContainsKey(node)){foreach (var neighbor in dependencies[node]){if (DFS(neighbor, dependencies, visited, path))return true;}}visited[node] = VisitState.Visited;path.RemoveAt(path.Count - 1);return false;}
}class Program
{static void Main(){var objA = new MyObject(1, "A", () => { Console.WriteLine("A 执行"); return 1; });var objB = new MyObject(2, "B", () => { Console.WriteLine("B 执行"); return 2; });var objC = new MyObject(3, "C", () => { Console.WriteLine("C 执行"); return 3; });var objD = new MyObject(4, "D", () => { Console.WriteLine("D 执行"); return 4; });var objE = new MyObject(5, "E", () => { Console.WriteLine("E 执行"); return 5; });var objF = new MyObject(6, "F", () => { Console.WriteLine("F 执行"); return 6; });var objects = new List<MyObject> { objA, objB, objC, objD, objE, objF };var dependencies = new Dictionary<int, List<int>>{{ 1, new List<int> { 2 } }, // A依赖B{ 2, new List<int> { 3 } }, // B依赖C{ 3, new List<int> { 1 } }, // C依赖A,形成环{ 4, new List<int> { 5 } }, // D依赖E{ 5, new List<int> { 6 } }  // E依赖F};try{var results = TopologicalSorter.SortAndExecute(objects, dependencies);Console.WriteLine("结果:" + string.Join(", ", results));}catch (InvalidOperationException ex){Console.WriteLine(ex.Message);}}
}

  

  copy进VS调试,还是错误的,遂又问:请测试上述修正后的代码,并找出环

  DeepSeek答:如下图(艹)

  

  

  我又接着问:C# 代码实现一个拓扑算法,给出例子

  DeepSeek答:如下图

  

  

  源代码在,copy进vs测试,还是无法找到环具体信息。

  又问:上一个回答中如果图中存在环,但无法给出环的具体信息,请修改代码后,给出存在环的图中具体环信息

  DeepSeek答:如下图

  

  

  源代码在给出的代码很接近了,不错还是无法得到全部循环依赖错误信息。

  我换了个思路,如果直接使用,DFS算法实现拓扑排序,是不是更好找出循环依赖?于是我就问:请使用DFS算法实现拓扑排序,当存在环时,输出环的具体信息,并给出例子

  DeepSeek答:如下图

  

  

  我服了,TM的到底是有多忙,这几天大白天问,都是这个鸟样。

  那就问豆包吧,问:结合上下文,使用DFS算法实现拓扑排序,当存在环时,输出环的具体信息,并给出例子

  豆包:

  

  运行后,这此算法已经非常接近了。

  我又继续问:请测试上一个回答的代码

  豆包:

  

  豆包回答说代码能运行通过,且输出正确信息,但是我运行还是错误的。

  我接着了一遍,请豆包修改代码,然后重新测试一遍,还是一样,有点小瑕疵。不过算很不错了。

非常接近答案的代码
 using System;
using System.Collections.Generic;// 定义对象类
class MyObject
{public int Id { get; }public string Name { get; }public Func<int> Action { get; }public MyObject(int id, string name, Func<int> action){Id = id;Name = name;Action = action;}public override string ToString(){return $"Object {Name} (ID: {Id})";}
}class TopologicalSorter
{// 用于标记节点的状态enum NodeState{Unvisited,Visiting,Visited}public static List<int> SortAndExecute(List<MyObject> objects, Dictionary<int, List<int>> dependencies){var graph = new Dictionary<int, List<int>>();foreach (var obj in objects){graph[obj.Id] = new List<int>();}foreach (var dep in dependencies){graph[dep.Key] = dep.Value;}var states = new Dictionary<int, NodeState>();foreach (var obj in objects){states[obj.Id] = NodeState.Unvisited;}var result = new List<int>();var stack = new Stack<int>();var cycle = new List<int>();foreach (var obj in objects){if (states[obj.Id] == NodeState.Unvisited){if (!DFS(obj.Id, graph, states, stack, ref cycle)){var cycleInfo = string.Join(" -> ", cycle);throw new InvalidOperationException($"依赖关系中存在环,环的节点顺序为: {cycleInfo}");}}}while (stack.Count > 0){int id = stack.Pop();MyObject obj = objects.Find(o => o.Id == id);result.Add(obj.Action());}return result;}private static bool DFS(int node, Dictionary<int, List<int>> graph, Dictionary<int, NodeState> states, Stack<int> stack, ref List<int> cycle){states[node] = NodeState.Visiting;cycle.Add(node);if (graph.ContainsKey(node)){foreach (var neighbor in graph[node]){if (states[neighbor] == NodeState.Visiting){// 发现环,回溯找出环的具体信息int startIndex = cycle.IndexOf(neighbor);if (startIndex != -1){cycle = cycle.GetRange(startIndex, cycle.Count - startIndex);}return false;}if (states[neighbor] == NodeState.Unvisited){if (!DFS(neighbor, graph, states, stack, ref cycle)){return false;}}}}states[node] = NodeState.Visited;stack.Push(node);cycle.RemoveAt(cycle.Count - 1);return true;}
}class Program
{static void Main(){// 创建多个对象var objA = new MyObject(1, "A", () =>{Console.WriteLine("A 对象正在执行操作...");return 1;});var objB = new MyObject(2, "B", () =>{Console.WriteLine("B 对象正在执行操作...");return 2;});var objC = new MyObject(3, "C", () =>{Console.WriteLine("C 对象正在执行操作...");return 3;});var objD = new MyObject(4, "D", () =>{Console.WriteLine("D 对象正在执行操作...");return 4;});var objE = new MyObject(5, "E", () =>{Console.WriteLine("E 对象正在执行操作...");return 5;});var objF = new MyObject(6, "F", () =>{Console.WriteLine("F 对象正在执行操作...");return 6;});var objects = new List<MyObject> { objA, objB, objC, objD, objE, objF };// 定义包含环的依赖关系var dependencies = new Dictionary<int, List<int>>{{ 1, new List<int> { 2 } }, // A 依赖 B{ 2, new List<int> { 3 } }, // B 依赖 C{ 3, new List<int> { 1 } }, // C 依赖 A,形成环{ 4, new List<int> { 5 } }, // D 依赖 E{ 5, new List<int> { 6 } }  // E 依赖 F};try{// 执行拓扑排序并按顺序执行对象操作var results = TopologicalSorter.SortAndExecute(objects, dependencies);Console.WriteLine("最终执行结果:");foreach (var result in results){Console.WriteLine(result);}}catch (InvalidOperationException ex){Console.WriteLine(ex.Message);}}
}

  看来,还是得我自己手动修改代码细节了,添加的代码

  然后给豆包发送:,给修正DFS算法后,发给了豆包。

  最后豆包回答我时,使用了我修改正的DFS算法。

  正确算法

总结

  AI确实能起到辅助作用,关键点在于,发送给AI的消息要能表达的具体点。至此就结束了。

  源代码 Learning-Case/TopologyAlgorithm at main · qiqiqiyaya/Learning-Case

 

C#版拓扑排序总结

语雀地址 拓扑排序

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/887406.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百万架构师第四十一课:RabbitMq:可靠性投递和实践经验|JavaGuide

来源:https://javaguide.net RabbitMQ 2-可靠性投递与生产实践 可靠性投递 ​ 首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。 如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。① 代…

jh

什么时候才能跟jh一样强啊 什么时候可以找回曾经的自己

Java基础知识day1

特性和优势 Java三大版本 JDK,JRE,JVM 环境搭建 Java运行机制 Hello,World!Java基础知识day1 特性和优势 简单性:去除了c++中一些复杂的内存管理和指针 面向对象:一种编程思想,其实Java开发是面向过程和面向对象同时进行 可移植性:每个机器上下载了JVM,就可…

java基础知识面试

1.为什么选择java 回答:1.java相对与c++是纯粹的面向对象编程,抛弃了c++的指针和继承的复杂使用。同时提供了丰富的内置库用于开发。2.一次编译,到处允许。将java代码编译为字节码,可通过jvm虚拟机编译成机器码在不同的环境下运行。3,具有安全性和健壮性,如数组越界机制和…

JAVA项目笔记--黑马店铺的优惠卷秒杀

功能实现介绍: 先判断优惠卷的信息保证不过期等,为了防止一个用户多次进行插入,要结合悲观锁。故 根据userId在redis生成分布式锁,使得之后的用户请求无法实现。 生成订单。是对优惠卷的数目进行更新,可以使用乐观锁,所以在插入前,判断某个值是否满足即库存是否大于0,如…

APISIX

ApiSix 使用ApiSix网关作为所有业务的流量入口,它提供了动态路由、动态上游、动态证书、A/B测试、灰度发布、限速、防攻击、收集指标、监控报警、可观测、服务治理,服务熔断身份认证等功能。主要用于管理和控制API流量,安全性,性能和可用性,APIsix的主要作用包括:API管理…

ES

ES参考文档:https://www.cnblogs.com/buchizicai/p/17093719.htmlES分布式搜索引擎注意:在没有创建库的时候搜索,ES会创建一个库并自动创建该字段并且设置为String类型也就是text什么是elasticsearch?一个开源的分布式搜索引擎,可以用来实现搜索,日志统计,分析,系统监控…

【codeforces】codeforces界面字体突然变得很大,页面布局改变解决办法

今天打开codeforces界面突然变成了这样左侧变成了这样恢复方法: 把滚轮拉倒最下面切换成电脑模式即可恢复正常

影刀RPA与Coze API的结合使用

网上找了些资料,但是发现好多都是用的 Coze 的历史接口,现在新的 V3 接口处理方式包括字段和处理方式都不一样了,所以现在这个教程是基于最新版 V3 接口的。配置好 API 后,在影刀 RPA 中使用。 一、API 介绍 开发文档 : https://www.coze.cn/docs/developer_guides/coze_a…

RPA与Coze API的结合使用

网上找了些资料,但是发现好多都是用的 Coze 的历史接口,现在新的 V3 接口处理方式包括字段和处理方式都不一样了,所以现在这个教程是基于最新版 V3 接口的。配置好 API 后,在影刀 RPA 中使用。 一、API 介绍 开发文档 : https://www.coze.cn/docs/developer_guides/coze_a…

电脑感觉速度比以前慢,清理了还是慢怎么办?你需要检查下CPU频率,看看是不是被锁频/降频了

0 问题 电脑总是感觉速度慢,清理了电脑,去掉了不必要的程序,还是感觉没有以前快。 我的是笔记本电脑,电脑外壳各个地方摸起来也不热,风扇转动正常。也没有灰尘,清理过。 1. 原因 一直也不知道咋回事,看系统进程时,无意中看到CPU频率仅有0.4GHz,且长期都是这样,这肯定不…