chore(CSharp): add Depth First Search (#447)

pull/448/head^2
Waqar Hassan Khan 2021-09-06 01:20:51 +06:00 committed by GitHub
parent f81fabe653
commit d057b243d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 199 additions and 1 deletions

View File

@ -18,4 +18,7 @@ For running the `.cs` file please using [.Net Finddle](https://dotnetfiddle.net/
- [Abundant Number](src/Maths/abundant-number.cs) - [Abundant Number](src/Maths/abundant-number.cs)
## Recusrsion ## Recusrsion
- [Factorial](src/Recursion/factorial.cs) - [Factorial](src/Recursion/factorial.cs)
## Graph
- [Depth First Search](src/Graph/depth-first-search.cs)

View File

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Algorithms.Graph
{
public class DepthFirstSearch
{
class Graph
{
private int _vertex;
private bool _cycleFound;
private List<List<int>> _adjacencyList;
private List<int> _parent;
private List<int> _visited;
private List<int> _traversal;
public const int WHITE = 0;
public const int GREY = 1;
public const int BLACK = 2;
public Graph(int vertex)
{
_vertex = vertex;
_traversal = new List<int>();
_adjacencyList = new List<List<int>>(vertex + 1);
for (int i = 0; i <= vertex; i++)
{
_adjacencyList.Add(new List<int>());
}
}
public void AddEdge(int start, int end)
{
_adjacencyList[start].Add(end);
}
public List<int> DFS(int source)
{
_parent = Enumerable.Repeat(-1, _vertex + 1).ToList();
_visited = Enumerable.Repeat(WHITE, _vertex + 1).ToList();
_traversal.Clear();
DFSRecursive(source);
return _traversal;
}
public bool HasCycle()
{
_parent = Enumerable.Repeat(-1, _vertex + 1).ToList();
_visited = Enumerable.Repeat(WHITE, _vertex + 1).ToList();
_traversal.Clear();
DFSRecursive(1);
return _cycleFound;
}
private void DFSRecursive(int source)
{
_visited[source] = GREY;
_traversal.Add(source);
foreach (int destination in _adjacencyList[source])
{
if (_visited[destination] == WHITE)
{
_parent[destination] = source;
DFSRecursive(destination);
}
else if (_visited[destination] == GREY && destination != _parent[source])
{
_cycleFound = true;
}
}
_visited[source] = BLACK;
}
}
public static List<int> DFS(int vertex, int src, List<Tuple<int, int>> edges)
{
Graph graph = new Graph(vertex);
foreach (var edge in edges)
{
graph.AddEdge(edge.Item1, edge.Item2);
graph.AddEdge(edge.Item2, edge.Item1);
}
return graph.DFS(src);
}
public static bool HasCycle(int vertex, List<Tuple<int, int>> edges)
{
Graph graph = new Graph(vertex);
foreach (var edge in edges)
{
graph.AddEdge(edge.Item1, edge.Item2);
graph.AddEdge(edge.Item2, edge.Item1);
}
return graph.HasCycle();
}
public static void Main()
{
List<Tuple<int, int>> edges = new List<Tuple<int, int>>();
edges.Add(new Tuple<int, int>(1, 2));
edges.Add(new Tuple<int, int>(1, 3));
edges.Add(new Tuple<int, int>(4, 3));
edges.Add(new Tuple<int, int>(3, 5));
List<int> traversal = DFS(5, 1, edges);
foreach (int v in traversal)
{
Console.Write($"{v} ");
}
Console.WriteLine($"Has Cycle: {HasCycle(5, edges)}");
}
}
}
/*
* depth first search for an undirected graph
* also cycles are detected
*/

View File

@ -0,0 +1,64 @@
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace Algorithms.Tests.Graph
{
[TestFixture]
public class DepthFirstSearch
{
static object[] DivideCasesForDFS =
{
new object[] { 5, 3, new List<Tuple<int, int>> {
new Tuple<int, int>(1, 2),
new Tuple<int, int>(1, 3),
new Tuple<int, int>(2, 3),
new Tuple<int, int>(4, 2),
new Tuple<int, int>(1, 5)
}, "3 1 2 4 5"
},
new object[] { 5, 1, new List<Tuple<int, int>> {
new Tuple<int, int>(1, 2),
new Tuple<int, int>(1, 3),
new Tuple<int, int>(4, 3),
new Tuple<int, int>(3, 5)
}, "1 2 3 4 5"
}
};
static object[] DivideCasesForCycleDetection =
{
new object[] { 5, new List<Tuple<int, int>> {
new Tuple<int, int>(1, 2),
new Tuple<int, int>(1, 3),
new Tuple<int, int>(2, 3),
new Tuple<int, int>(4, 2),
new Tuple<int, int>(1, 5)
}, true
},
new object[] { 5, new List<Tuple<int, int>> {
new Tuple<int, int>(1, 2),
new Tuple<int, int>(1, 3),
new Tuple<int, int>(4, 3),
new Tuple<int, int>(3, 5)
}, false
}
};
[TestCaseSource(nameof(DivideCasesForDFS))]
public void TestDFS_ShouldGetExpectedResult(int vertex, int source, List<Tuple<int, int>> edges, string expected)
{
List<int> result = Algorithms.Graph.DepthFirstSearch.DFS(vertex, source, edges);
Assert.AreEqual(expected, string.Join(' ', result));
}
[TestCaseSource(nameof(DivideCasesForCycleDetection))]
public void TestCycleDetection_ShouldGetExpectedResult(int vertex, List<Tuple<int, int>> edges, bool expected)
{
bool result = Algorithms.Graph.DepthFirstSearch.HasCycle(vertex, edges);
Assert.AreEqual(expected, result);
}
}
}