-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGraph.cs
More file actions
158 lines (131 loc) · 4.6 KB
/
Copy pathGraph.cs
File metadata and controls
158 lines (131 loc) · 4.6 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using Algorithms.Implementation;
using System.Collections.Generic;
using static ClassLibrary2.GraphAlgorithms;
namespace ClassLibrary2
{
public class GraphAlgorithms
{
#region Topological sort
public class Node<T>
{
public T Value { get; set; }
public List<Node<T>> DependsOn { get; set; }
public List<Node<T>> DependentBy { get; set; }
public Node(T value)
{
Value = value;
DependsOn = new List<Node<T>>();
DependentBy = new List<Node<T>>();
}
}
public class Graph<T>
{
public Dictionary<T, Node<T>> Nodes { get; set; }
public Graph()
{
Nodes = new Dictionary<T, Node<T>>();
}
}
public static List<Node<char>> TopologicalSort()
{
var aNode = new Node<char>('A');
var bNode = new Node<char>('B');
var cNode = new Node<char>('C');
var dNode = new Node<char>('D');
aNode.DependsOn.Add(bNode);
bNode.DependentBy.Add(aNode);
aNode.DependsOn.Add(cNode);
cNode.DependentBy.Add(aNode);
cNode.DependsOn.Add(dNode);
dNode.DependentBy.Add(cNode);
// cycle
dNode.DependsOn.Add(cNode);
cNode.DependentBy.Add(dNode);
var graph = new Graph<char>();
graph.Nodes.Add('A', aNode);
graph.Nodes.Add('B', bNode);
graph.Nodes.Add('C', cNode);
graph.Nodes.Add('D', dNode);
var toVisit = new Queue<Node<char>>();
var ordered = new List<Node<char>>();
foreach (var node in graph.Nodes.Values)
{
if (node.DependsOn.Count == 0)
{
toVisit.Enqueue(node);
}
}
while (toVisit.Count > 0)
{
var currentNode = toVisit.Dequeue();
ordered.Add(currentNode);
foreach (var dependentNode in currentNode.DependentBy)
{
dependentNode.DependsOn.Remove(currentNode);
if (dependentNode.DependsOn.Count == 0)
{
toVisit.Enqueue(dependentNode);
}
}
}
if (ordered.Count < graph.Nodes.Count)
{
return null;
}
return ordered;
}
#endregion
#region shortest path
public static List<int> ShortestPath(int[] input)
{
var bestDistanceToPosition = new Dictionary<int, int>();
var nodesToVisit = new PriorityQueue<int>((a, b) => bestDistanceToPosition[a] - bestDistanceToPosition[b]);
var path = new List<int>();
var previous = new int[input.Length];
for (int i = 0; i < input.Length; i++)
{
if (i == 0)
{
bestDistanceToPosition[i] = 0;
}
else
{
bestDistanceToPosition[i] = int.MaxValue;
}
nodesToVisit.Add(i);
}
while (nodesToVisit.Storage.Count > 0)
{
// Find node with minimum distance to
var closestNode = nodesToVisit.ExtractRoot();
if (closestNode == (input.Length - 1))
{
path = new List<int>();
while (closestNode != 0)
{
path.Add(closestNode);
closestNode = previous[closestNode];
}
path.Reverse();
return path;
}
if (bestDistanceToPosition[closestNode] == int.MaxValue)
{
return null;
}
for (int i = 1; i <= input[closestNode] && closestNode + i < input.Length; i++)
{
var distanceToNext = bestDistanceToPosition[closestNode] + 1;
if (distanceToNext < bestDistanceToPosition[closestNode + i])
{
bestDistanceToPosition[closestNode + i] = distanceToNext;
// TODO: need to bubble up the vertex in the heap
previous[closestNode + i] = closestNode;
}
}
}
return null;
}
#endregion
}
}