1- using System . Collections . Generic ;
2- using System . Linq ;
1+ using System ;
2+ using System . Collections . Generic ;
33
4- /**
5- * A generic implementation of the Dijkstra algorithm for weighted graphs.
6- * @author Vivian Umansky
7- * @since 2023-12
8- */
94public class Dijkstra
105{
6+ /**
7+ * A generic implementation of the Dijkstra algorithm for weighted graphs.
8+ * @param graph The graph implementing the IGraph interface.
9+ * @param startNode The starting node.
10+ * @param endNode The target node.
11+ * @param getEdgeWeight A function to get the weight of an edge between two nodes.
12+ * @param maxIterations The maximum number of iterations before giving up.
13+ * @return A list of nodes representing the shortest path, or an empty list if no path exists.
14+ */
1115 public static List < NodeType > GetPath < NodeType > (
1216 IGraph < NodeType > graph ,
1317 NodeType startNode ,
1418 NodeType endNode ,
15- System . Func < NodeType , NodeType , float > getEdgeWeight ,
19+ Func < NodeType , NodeType , float > getEdgeWeight ,
1620 int maxIterations = 1000
17- ) where NodeType : notnull // Ensure NodeType is non-nullable
21+ ) where NodeType : notnull
1822 {
1923 var distances = new Dictionary < NodeType , float > ( ) ;
2024 var previousNodes = new Dictionary < NodeType , NodeType > ( ) ;
2125 var visited = new HashSet < NodeType > ( ) ;
22- var priorityQueue = new SortedSet < ( float , NodeType ) > ( Comparer < ( float , NodeType ) > . Create ( ( a , b ) =>
23- a . Item1 != b . Item1 ? a . Item1 . CompareTo ( b . Item1 ) : Comparer < NodeType > . Default . Compare ( a . Item2 , b . Item2 ) ) ) ;
26+ var priorityQueue = new SortedSet < ( float , NodeType ) > (
27+ Comparer < ( float , NodeType ) > . Create ( ( a , b ) =>
28+ a . Item1 != b . Item1
29+ ? a . Item1 . CompareTo ( b . Item1 )
30+ : a . Item2 . GetHashCode ( ) . CompareTo ( b . Item2 . GetHashCode ( ) ) )
31+ ) ;
2432
25- // Initialize distances and add the start node to the queue
33+
34+ // Initialize distances and priority queue
2635 distances [ startNode ] = 0 ;
2736 priorityQueue . Add ( ( 0 , startNode ) ) ;
2837
2938 for ( int iteration = 0 ; iteration < maxIterations ; iteration ++ )
3039 {
31- if ( priorityQueue . Count == 0 )
32- break ;
40+ if ( priorityQueue . Count == 0 ) break ;
3341
34- var ( currentDistance , currentNode ) = priorityQueue . First ( ) ;
35- priorityQueue . Remove ( priorityQueue . First ( ) ) ;
42+ var ( currentDistance , currentNode ) = priorityQueue . Min ;
43+ priorityQueue . Remove ( priorityQueue . Min ) ;
3644
37- if ( visited . Contains ( currentNode ) )
38- continue ;
45+ if ( visited . Contains ( currentNode ) ) continue ;
3946
4047 visited . Add ( currentNode ) ;
4148
42- if ( currentNode . Equals ( endNode ) )
43- break ;
49+ if ( currentNode . Equals ( endNode ) ) break ;
4450
4551 foreach ( var neighbor in graph . Neighbors ( currentNode ) )
4652 {
47- if ( visited . Contains ( neighbor ) )
48- continue ;
53+ if ( visited . Contains ( neighbor ) ) continue ;
4954
5055 float edgeWeight = getEdgeWeight ( currentNode , neighbor ) ;
56+ if ( edgeWeight == float . MaxValue ) continue ; // Ignore unreachable tiles
57+
5158 float newDistance = currentDistance + edgeWeight ;
5259
5360 if ( ! distances . ContainsKey ( neighbor ) || newDistance < distances [ neighbor ] )
@@ -56,26 +63,26 @@ public static List<NodeType> GetPath<NodeType>(
5663 {
5764 priorityQueue . Remove ( ( distances [ neighbor ] , neighbor ) ) ;
5865 }
66+
5967 distances [ neighbor ] = newDistance ;
60- previousNodes [ neighbor ] = currentNode ! ;
68+ previousNodes [ neighbor ] = currentNode ;
6169 priorityQueue . Add ( ( newDistance , neighbor ) ) ;
6270 }
6371 }
6472 }
6573
66- // Construct the path
74+ // Reconstruct the shortest path
6775 var path = new List < NodeType > ( ) ;
6876 if ( previousNodes . ContainsKey ( endNode ) || startNode . Equals ( endNode ) )
6977 {
70- for ( var current = endNode ; current != null ; current = previousNodes . ContainsKey ( current ) ? previousNodes [ current ] : default ( NodeType ) )
78+ for ( var current = endNode ; current != null ; current = previousNodes . GetValueOrDefault ( current ) )
7179 {
7280 path . Add ( current ) ;
73- if ( current . Equals ( startNode ) )
74- break ;
81+ if ( current . Equals ( startNode ) ) break ;
7582 }
7683 path . Reverse ( ) ;
7784 }
7885
7986 return path ;
8087 }
81- }
88+ }
0 commit comments