예제 #1
0
        /// <summary>
        /// Finds the shortest path with specified start and end using breath first search.
        /// </summary>
        /// <typeparam name="TNode">The value contained in the node.</typeparam>
        /// <param name="start">The start node.</param>
        /// <param name="end">The end node.</param>
        public static IEnumerable <Node <TNode> > FindShortestPath <TNode>(Node <TNode> start, Node <TNode> end)
        {
            var frontier = new Queue <Node <TNode> >();

            frontier.Enqueue(start);

            var visitedNodes = new NodeDictionary <TNode>();

            visitedNodes.Add(start);

            while (frontier.Count > 0)
            {
                var currentNode = frontier.Dequeue();

                if (currentNode.Equals(end))
                {
                    break;
                }

                foreach (var edge in currentNode.Edges)
                {
                    if (!visitedNodes.Contains(edge.Target))
                    {
                        frontier.Enqueue(edge.Target);
                        visitedNodes.Add(edge.Target, currentNode);
                    }
                }
            }

            var path = BacktrackPathTo(end, visitedNodes);

            return(path);
        }
예제 #2
0
        /// <summary>
        /// Finds the cheapest path with specified start and end using the Dijkstra algorithm (AKA Uniform Cost Search).
        /// </summary>
        /// <typeparam name="TNode">The value contained in the node.</typeparam>
        /// <param name="start">The start node.</param>
        /// <param name="end">The end node.</param>
        /// <param name="graph">The graph to operate on.</param>
        public static IEnumerable <Node <TNode> > FindCheapestPath <TNode>(Node <TNode> start, Node <TNode> end, UndirectedGraph <TNode> graph)
        {
            var frontier = new Queue <Node <TNode> >();

            frontier.Enqueue(start);

            var visitedNodes = new NodeDictionary <TNode>();

            visitedNodes.Add(start);

            var costs = InitializeCosts(graph);

            costs[start] = 0d;

            while (frontier.Count > 0)
            {
                var currentNode = frontier.Dequeue();

                if (currentNode.Equals(end))
                {
                    break;
                }

                var prioritizedEdges = new PriorityQueue <Edge <TNode> >(currentNode.Edges);

                while (prioritizedEdges.Count > 0)
                {
                    var edge = prioritizedEdges.Dequeue();

                    var currentCost = costs[edge.Target];
                    var newCost     = costs[currentNode] + edge.Weight;

                    if (newCost < currentCost)
                    {
                        costs[edge.Target] = newCost;

                        // A cheaper path is found, so the target node predecesor must be replaced with the current node.
                        if (visitedNodes.Contains(edge.Target))
                        {
                            visitedNodes[edge.Target] = currentNode;
                        }
                    }

                    if (!visitedNodes.Contains(edge.Target))
                    {
                        frontier.Enqueue(edge.Target);
                        visitedNodes.Add(edge.Target, currentNode);
                    }
                }
            }

            var path = BacktrackPathTo(end, visitedNodes);

            return(path);
        }
예제 #3
0
        private static IEnumerable <Node <TNode> > BacktrackPathTo <TNode>(Node <TNode> end, NodeDictionary <TNode> visitedNodes)
        {
            LinkedList <Node <TNode> > path = new LinkedList <Node <TNode> >();

            Node <TNode> current  = end;
            Node <TNode> previous = null;

            if (visitedNodes.Contains(end))
            {
                current  = end;
                previous = visitedNodes.GetPrevious(current);
            }

            while (previous != null)
            {
                path.AddFirst(current);

                current  = previous;
                previous = visitedNodes.GetPrevious(current);
            }

            path.AddFirst(current);

            return(path);
        }