示例#1
0
 /// <summary>
 /// Operation: O(1)
 /// </summary>
 public void AddEdgeTo(AdjacencyNode <T> node)
 {
     if (!HasEdgeTo(node))
     {
         _adjacentNodes.Add(node.Value, node);
     }
 }
示例#2
0
 private void AddNodeIfNotAlreadyContained(AdjacencyNode <T> node)
 {
     if (!_nodes.ContainsKey(node.Value))
     {
         _nodes.Add(node.Value, node);
     }
 }
示例#3
0
        public bool Equals(AdjacencyNode <T> f)
        {
            if (f == null)
            {
                return(false);
            }

            return(Value.Equals(f.Value));
        }
示例#4
0
        public override bool Equals(object obj)
        {
            AdjacencyNode <T> f = obj as AdjacencyNode <T>;

            if (f == null)
            {
                return(false);
            }

            return(Equals(f));
        }
示例#5
0
        /// <summary>
        /// If we add an edge it checks if the node as already there, otherwise it adds the node.
        ///
        /// Operation: O(1)
        /// </summary>
        public void AddEdge(T node1, T node2)
        {
            var startNode = _nodes.ContainsKey(node1) ? _nodes[node1] : null;

            if (startNode == null)
            {
                startNode = new AdjacencyNode <T>(node1);
                AddNodeIfNotAlreadyContained(startNode);
            }

            var endNode = _nodes.ContainsKey(node2) ? _nodes[node2] : null;

            if (endNode == null)
            {
                endNode = new AdjacencyNode <T>(node2);
                AddNodeIfNotAlreadyContained(endNode);
            }

            startNode.AddEdgeTo(endNode);
            endNode.AddEdgeTo(startNode);
        }
示例#6
0
        /// <summary>
        /// Gets the path from the source to the destination. It does include the destination as its last point. The first point
        /// is not the source but the first neighbour of it.
        ///
        /// Operation executes in O(n)
        ///
        /// Note: before we can get a path we need to run the algorithm
        /// </summary>
        public LinkedList <T> GetShortestPathTo(T destination)
        {
            if (Source == null)
            {
                throw new InvalidOperationException("You need to Run the algorithm first before calculating paths...");
            }

            AdjacencyNode <T> destinationNode = new AdjacencyNode <T>(destination);

            // building path going back from the destination to the source always taking the nearest node
            LinkedList <T> path = new LinkedList <T>();

            path.AddFirst(destinationNode.Value);

            while (PreviousNode[destinationNode] != null)
            {
                destinationNode = PreviousNode[destinationNode];
                path.AddFirst(destinationNode.Value);
            }

            path.RemoveFirst();

            return(path);
        }
示例#7
0
 /// <summary>
 /// Operation: O(1)
 /// </summary>
 public bool HasEdgeTo(AdjacencyNode <T> node)
 {
     return(_adjacentNodes.ContainsKey(node.Value));
 }
示例#8
0
 /// <summary>
 /// Operation: O(1)
 /// </summary>
 public void RemoveEdgeTo(AdjacencyNode <T> node)
 {
     _adjacentNodes.Remove(node.Value);
 }
示例#9
0
        /// <summary>
        /// Runs the Dijkstra algorithm which calculates the shortest paths from the source to any other node
        /// which is reachable from there.
        ///
        /// If this method is called multiple times with the same source it does only calculate the paths the first time
        ///
        /// Exceptions:
        /// ArgumentException if the nodes Enumerable is null, the source is null or the source is not part of the graph (the nodes)
        /// </summary>
        public void Run(IEnumerable <AdjacencyNode <T> > nodes, AdjacencyNode <T> source)
        {
            if (nodes == null || source == null)
            {
                throw new ArgumentException("Nodes Enumerable or Source is null");
            }

            if (Source != null && Source.Equals(source))
            {
                return;
            }

            /**
             * Initialize the Algorithm
             */
            Source = source;

            // Holds the shortest distance between the source and the node
            Dictionary <AdjacencyNode <T>, int> distance = new Dictionary <AdjacencyNode <T>, int>();

            // Holds the node from which we need to go to the current node if we are taking the shortest path
            PreviousNode = new Dictionary <AdjacencyNode <T>, AdjacencyNode <T> >();
            // Fast Access to the Node (of the Nodes to inspect) which has the shortest distance and thus needs to be processed next
            // if we processed all nodes in that queue or the remaining ones are not reachable the algorithm is finished
            HeapPriorityQueue <AdjacencyNode <T> > distanceQueue = new HeapPriorityQueue <AdjacencyNode <T> >();

            foreach (AdjacencyNode <T> n in nodes)
            {
                // previous nodes are unknown at the start
                PreviousNode.Add(n, null);
                // distance is assumed to be the maximum possible value. Therefore it can be improved if we find a shorter one
                distance.Add(n, int.MaxValue);
                distanceQueue.Enqueue(n, int.MaxValue);
            }

            if (!distanceQueue.Contains(source))
            {
                throw new ArgumentException("The source is not part of the graph (nodes)");
            }

            /**
             * Execute the Algorithm
             */
            distance[Source] = 0;
            distanceQueue.UpdatePriority(Source, 0);

            while (!distanceQueue.IsEmpty())
            {
                // The nearest node is a node which has never been reached (otherwise its path would have been improved)
                // This means all other nodes can also not be reached and our algorithm is finished...
                if (distanceQueue.PeekPriority() == int.MaxValue)
                {
                    break;
                }

                AdjacencyNode <T> nearestNode = distanceQueue.Dequeue();

                // Check all neighbours that still need to be inspected
                foreach (AdjacencyNode <T> neighbour in nearestNode.AdjacentNodes)
                {
                    if (!distanceQueue.Contains(neighbour))
                    {
                        continue;
                    }

                    // calculate distance with the currently inspected neighbour
                    int neighbourDist = distance[nearestNode] + 1;

                    // set the neighbour as shortest if it is better than the currently known shortest distance
                    if (neighbourDist < distance[neighbour])
                    {
                        distance[neighbour] = neighbourDist;
                        distanceQueue.UpdatePriority(neighbour, neighbourDist);
                        PreviousNode[neighbour] = nearestNode;
                    }
                }
            }
        }