c#实现图的拓扑排序、深度优先、广度优先两种算法
原文链接:https://blog.csdn.net/MfuuJava/article/details/132933517
拓扑排序是一种在有向无环图(DAG)中对节点进行排序的算法。
在 C# 中,我们可以使用深度优先搜索(DFS)和拓扑排序算法来解决这个问题。
深度优先代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | using System; using System.Collections.Generic; class Graph { private int V; // 图中节点的数量 private List<List< int >> adj; // 邻接列表 // 构造函数 public Graph( int v) { V = v; adj = new List<List< int >>(v); for ( int i = 0; i < v; ++i) adj.Add( new List< int >()); } // 添加边 public void AddEdge( int v, int w) { adj[v].Add(w); } // 拓扑排序的辅助函数 private void TopologicalSortUtil( int v, bool [] visited, Stack< int > stack) { visited[v] = true ; foreach ( int i in adj[v]) { if (!visited[i]) TopologicalSortUtil(i, visited, stack); } stack.Push(v); } // 执行拓扑排序 public void TopologicalSort() { Stack< int > stack = new Stack< int >(); bool [] visited = new bool [V]; for ( int i = 0; i < V; i++) visited[i] = false ; for ( int i = 0; i < V; i++) { if (visited[i] == false ) TopologicalSortUtil(i, visited, stack); } // 打印排序结果 while (stack.Count > 0) { Console.Write(stack.Pop() + " " ); } } // 测试 public static void Main( string [] args) { Graph graph = new Graph(6); graph.AddEdge(5, 2); graph.AddEdge(5, 0); graph.AddEdge(4, 0); graph.AddEdge(4, 1); graph.AddEdge(2, 3); graph.AddEdge(3, 1); Console.WriteLine( "拓扑排序结果:" ); graph.TopologicalSort(); Console.ReadKey(); } } |
在上述代码中,我们首先定义了一个 Graph 类,用于表示有向无环图。Graph 类包含了图中节点的数量和一个邻接列表 adj,用于存储图的边。
我们使用 AddEdge 方法向图中添加边。然后,在 TopologicalSortUtil 方法中,我们使用搜索来遍历图,并将访问过的节点压入栈中。
最后,在 TopologicalSort 方法中,我们遍历图中的所有节点,并调用 TopologicalSortUtil 方法进行拓扑排序。最终,我们打印栈中的元素,即可得到拓扑排序的结果。
在上述示例中,我们创建了一个包含6个节点的图,并添加了一些边。然后,我们执行拓扑排序,并打印排序结果。
广度优先:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | using System; using System.Collections.Generic; public class Graph { private int V; //图中节点的个数 private List< int >[] adj; //图的邻接表 public Graph( int v) { V = v; adj = new List< int >[v]; for ( int i = 0; i < v; ++i) adj[i] = new List< int >(); } public void AddEdge( int v, int w) { adj[v].Add(w); //将节点w加入节点v的邻接表中 } public void TopologicalSort() { int [] indegree = new int [V]; //用于统计每个节点的入度 for ( int i = 0; i < V; ++i) indegree[i] = 0; //统计每个节点的入度 for ( int v = 0; v < V; ++v) { List< int > adjList = adj[v]; foreach ( int w in adjList) indegree[w]++; } Queue< int > queue = new Queue< int >(); //存放入度为0的节点 for ( int i = 0; i < V; ++i) { if (indegree[i] == 0) queue.Enqueue(i); } List< int > result = new List< int >(); //存放排序结果 int count = 0; //已经排序的节点个数 while (queue.Count > 0) { int v = queue.Dequeue(); result.Add(v); count++; //将与节点v相邻的节点的入度减1 List< int > adjList = adj[v]; foreach ( int w in adjList) { indegree[w]--; if (indegree[w] == 0) queue.Enqueue(w); } } //判断是否有环 if (count != V) { Console.WriteLine( "图中存在环!" ); return ; } //输出排序结果 Console.WriteLine( "拓扑排序结果:" ); foreach ( int v in result) { Console.Write(v + " " ); } } } public class Program { public static void Main( string [] args) { Graph g = new Graph(6); g.AddEdge(5, 2); g.AddEdge(5, 0); g.AddEdge(4, 0); g.AddEdge(4, 1); g.AddEdge(2, 3); g.AddEdge(3, 1); g.TopologicalSort(); Console.ReadKey(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | using System; using System.Collections.Generic; public class TopologicalSort { private Dictionary< char , HashSet< char >> graph; private Dictionary< char , int > inDegrees; public TopologicalSort(Dictionary< char , HashSet< char >> graph) { this .graph = graph; inDegrees = new Dictionary< char , int >(); foreach ( var vertex in graph.Keys) { if (!inDegrees.ContainsKey(vertex)) { inDegrees[vertex] = 0; } foreach ( var neighbor in graph[vertex]) { if (!inDegrees.ContainsKey(neighbor)) { inDegrees[neighbor] = 0; } inDegrees[neighbor]++; } } } public List< char > Sort() { Queue< char > sources = new Queue< char >(); List< char > sorted = new List< char >(); foreach ( var vertex in inDegrees.Keys) { if (inDegrees[vertex] == 0) { sources.Enqueue(vertex); } } while (sources.Count > 0) { char vertex = sources.Dequeue(); sorted.Add(vertex); foreach ( var neighbor in graph[vertex]) { inDegrees[neighbor]--; if (inDegrees[neighbor] == 0) { sources.Enqueue(neighbor); } } } if (sorted.Count != inDegrees.Count) { throw new InvalidOperationException( "Graph has a cycle" ); } return sorted; } } // 使用示例 public class Program { public static void Main() { var graph = new Dictionary< char , HashSet< char >>() { { 'A' , new HashSet< char >() { 'B' , 'C' } }, { 'B' , new HashSet< char >() { 'D' , 'E' } }, { 'C' , new HashSet< char >() { 'F' } }, { 'D' , new HashSet< char >() { 'E' } }, { 'E' , new HashSet< char >() { 'F' } }, { 'F' , new HashSet< char >() { } } }; TopologicalSort topologicalSort = new TopologicalSort(graph); List< char > sorted = topologicalSort.Sort(); foreach ( char vertex in sorted) { Console.WriteLine(vertex); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-03-20 RadioButtonList的属性以及RadioButtonList显示隐藏ListItem的值;默认选中Listitem的值;设置某列不可用