-
Notifications
You must be signed in to change notification settings - Fork 295
Expand file tree
/
Copy pathBiDirectional.cs
More file actions
95 lines (79 loc) · 2.92 KB
/
BiDirectional.cs
File metadata and controls
95 lines (79 loc) · 2.92 KB
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
90
91
92
93
94
95
using Advanced.Algorithms.DataStructures.Graph;
using Advanced.Algorithms.DataStructures.Graph.AdjacencyList;
using System.Collections.Generic;
namespace Advanced.Algorithms.Graph
{
/// <summary>
/// A BiDirectional Path Search on DiGraph.
/// </summary>
public class BiDirectional<T>
{
/// <summary>
/// Returns true if Path exists from source to destination.
/// </summary>
public bool PathExists(IGraph<T> graph, T source, T destination)
{
return bfs(graph, source, destination);
}
/// <summary>
/// Use breadth First Search from Source and Target until they meet.
/// If they could'nt find the element before they meet return false.
/// </summary>
private bool bfs(IGraph<T> graph, T source, T destination)
{
var visitedA = new HashSet<T>();
var visitedB = new HashSet<T>();
var bfsQueueA = new Queue<IGraphVertex<T>>();
var bfsQueueB = new Queue<IGraphVertex<T>>();
bfsQueueA.Enqueue(graph.GetVertex(source));
bfsQueueB.Enqueue(graph.GetVertex(destination));
visitedA.Add(graph.GetVertex(source).Key);
visitedB.Add(graph.GetVertex(destination).Key);
//search from both ends for a Path
while (true)
{
if (bfsQueueA.Count > 0)
{
var current = bfsQueueA.Dequeue();
//intersects with search from other end
if (visitedB.Contains(current.Key))
{
return true;
}
foreach (var edge in current.Edges)
{
if (visitedA.Contains(edge.TargetVertexKey))
{
continue;
}
visitedA.Add(edge.TargetVertexKey);
bfsQueueA.Enqueue(edge.TargetVertex);
}
}
if (bfsQueueB.Count > 0)
{
var current = bfsQueueB.Dequeue();
//intersects with search from other end
if (visitedA.Contains(current.Key))
{
return true;
}
foreach (var edge in current.Edges)
{
if (visitedB.Contains(edge.TargetVertexKey))
{
continue;
}
visitedB.Add(edge.TargetVertexKey);
bfsQueueB.Enqueue(edge.TargetVertex);
}
}
if(bfsQueueA.Count == 0 && bfsQueueB.Count == 0)
{
break;
}
}
return false;
}
}
}