Integrating SharpGraphLib into ASP.NET and Desktop Applications

From Trees to DAGs: Practical Examples Using SharpGraphLib

This tutorial shows practical examples of using SharpGraphLib (a C# graph library) to model trees and directed acyclic graphs (DAGs). It covers creating graphs, traversals, common algorithms, and small real-world examples with compact, copy-paste-ready code snippets.

Prerequisites

  • .NET 6+ or compatible SDK
  • SharpGraphLib referenced via NuGet (assumed package id: SharpGraphLib). Install:

bash

dotnet add package SharpGraphLib
  • Basic C# knowledge

1. Modeling a Tree

A tree is a directed graph where each node (except the root) has exactly one parent and there are no cycles. Use trees for hierarchical data: file systems, organization charts, parse trees.

Code: Define nodes and build a simple tree

csharp

using SharpGraphLib; using System; class TreeExample { static void Main() { var graph = new DirectedGraph<string>(); // Create nodes graph.AddVertex(“Root”); graph.AddVertex(“A”); graph.AddVertex(“B”); graph.AddVertex(“A1”); graph.AddVertex(“A2”); graph.AddVertex(“B1”); // Add edges (parent -> child) graph.AddEdge(“Root”, “A”); graph.AddEdge(“Root”, “B”); graph.AddEdge(“A”, “A1”); graph.AddEdge(“A”, “A2”); graph.AddEdge(“B”, “B1”); Console.WriteLine(“Pre-order traversal:”); foreach (var v in GraphTraversal.PreOrder(graph, “Root”)) Console.WriteLine(v); } }

Traversal: Pre-order and Post-order

Use depth-first search to produce pre-order/post-order sequences. Example utility (if SharpGraphLib lacks helpers):

csharp

public static class GraphTraversal { public static IEnumerable<T> PreOrder<T>(DirectedGraph<T> g, T root) { var visited = new HashSet<T>(); var stack = new Stack<T>(); stack.Push(root); while (stack.Count > 0) { var node = stack.Pop(); if (!visited.Add(node)) continue; yield return node; // push children in reverse to visit in insertion order foreach (var child in g.GetOutgoing(node).Reverse()) stack.Push(child); } } }

2. Converting a Tree to a DAG (sharing subtrees)

When multiple parents reference identical substructures, convert the tree to a DAG by reusing vertices. Example: expression trees with common subexpressions.

Code: Build expression tree with shared nodes

csharp

var dag = new DirectedGraph<string>(); dag.AddVertex(“x”); dag.AddVertex(“y”); dag.AddVertex(“add”); // represents (x + y) dag.AddVertex(“mul”); // represents (add * y) // edges for add: add -> x, add -> y dag.AddEdge(“add”, “x”); dag.AddEdge(“add”, “y”); // reuse ‘add’ as input to mul dag.AddEdge(“mul”, “add”); dag.AddEdge(“mul”, “y”);

3. Topological Sort on DAGs

Topological sorting orders vertices so every directed edge u->v has u before v. Useful for build systems, task scheduling, dependency resolution.

Code: Kahn’s algorithm (implementation)

csharp

public static IList<T> TopologicalSort<T>(DirectedGraph<T> g) { var inDegree = new Dictionary<T,int>(); foreach (var v in g.Vertices) inDegree[v] = 0; foreach (var u in g.Vertices) foreach (var v in g.GetOutgoing(u)) inDegree[v]++; var q = new Queue<T>(inDegree.Where(kv => kv.Value==0).Select(kv => kv.Key)); var result = new List<T>(); while (q.Count > 0) { var n = q.Dequeue(); result.Add(n); foreach (var m in g.GetOutgoing(n)) { inDegree[m]; if (inDegree[m]==0) q.Enqueue(m); } } if (result.Count != inDegree.Count) throw new InvalidOperationException(“Graph has at least one cycle.”); return result; }

4. Detecting Cycles (ensure DAG)

Use DFS color marking or Kahn’s algorithm failure to detect cycles.

Code: DFS cycle detection

csharp

public static bool HasCycle<T>(DirectedGraph<T> g) { var color = g.Vertices.ToDictionary(v => v, v => 0); // 0=white,1=gray,2=black bool Dfs(T u) { color[u] = 1; foreach (var v in g.GetOutgoing(u)) { if (color[v] == 1) return true; if (color[v] == 0 && Dfs(v)) return true; } color[u] = 2; return false; } foreach (var v in g.Vertices) if (color[v] == 0 && Dfs(v)) return true; return false; }

5. Practical Examples

Example A — Build System Dependency

  • Vertices: projects/files
  • Edges: A -> B if A depends on B
  • Use TopologicalSort to determine build order. Short snippet: use TopologicalSort(dag)

Example B — Task Scheduling with Shared Resources

  • Create DAG of tasks; common subtask nodes reused to avoid duplicate work. Run topological order and execute in sequence, parallelizing nodes with zero in-degree.

Example C — Expression DAG for Memoized Evaluation

  • Reuse identical subexpressions as single vertices; evaluate in topological order to compute outputs once.

6. Performance Tips

  • Use adjacency lists and HashSet for vertices for O(1) lookups.
  • Cache out-degrees/in-degrees if running many queries.
  • For large graphs, prefer iterative algorithms (Kahn) to avoid recursion depth issues.

7. Summary

  • Trees are simple directed graphs without cycles and with unique parent per node.
  • DAGs allow shared substructures; use topological sort for ordering.
  • Common operations: traversal, cycle detection, topological sort, and reuse of nodes to convert trees into DAGs.

If you want, I can convert these snippets into a runnable sample project (Program.cs + csproj).

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *