//Remove a node from the graph, and thus all of the edges connected to it public void removeNode(NodeMx <T> x) { //First remove all edges invovling this node for (int n = 0; n < edges.Count; n++) { if (edges[n].nodes[0].identifier == x.identifier || edges[n].nodes[1].identifier == x.identifier) { //First remove the edge from the 2 nodes it connects edges[n].nodes[0].removeEdge(edges[n]); if (!edges[n].isDirected) { edges[n].nodes[1].removeEdge(edges[n]); } //Then remove from the graph edges.RemoveAt(n); edges.TrimExcess(); n = n - 1; //So we don't skip an element after removal } } edgeCount = edges.Count; //Then remove the node from the graph completely for (int n = 0; n < nodes.Count; n++) { if (nodes[n].identifier == x.identifier) { nodes.RemoveAt(n); nodes.TrimExcess(); nodeCount = nodes.Count; break; } } }
public static List <NodeMx <int> > BFS(GraphMx <int> G, int startNode) { List <NodeMx <int> > foundNodes = new List <NodeMx <int> >(); Queue exploredNodes = new Queue(); exploredNodes.Enqueue(G.nodes[startNode]); G.nodes[startNode].isVisited = true; while (exploredNodes.Count != 0) { NodeMx <int> v = (NodeMx <int>)exploredNodes.Dequeue(); foundNodes.Add(v); for (int n = 0; n < v.nodeEdges.Count; n++) { NodeMx <int> w = v.nodeEdges[n].nodes[1]; if (w.isVisited == false) { w.isVisited = true; exploredNodes.Enqueue(w); } } } return(foundNodes); }
//If the edge is directed then the convention is that a is the tail, and b is the head public EdgeMx(NodeMx <T> a, NodeMx <T> b, bool directed, int i) { nodes[0] = a; nodes[1] = b; isDirected = directed; identifier = i; }
//If the edge is un directed but weighted public EdgeMx(NodeMx <T> a, NodeMx <T> b, double edgeWeigt, int i) { nodes[0] = a; nodes[1] = b; isWeighted = true; weight = edgeWeigt; identifier = i; }
//Adds a directed weighted connection between nodes a and b public void addDirectedConnection(NodeMx <T> a, NodeMx <T> b, double w) { EdgeMx <T> edgeA = new EdgeMx <T>(a, b, w, uniqueNodeID); edges.Add(edgeA); a.addEdge(edgeA); edgeCount = edges.Count; uniqueNodeID++; }
public int CompareTo(object obj) { if (obj == null) { return(1); } NodeMx <T> n = obj as NodeMx <T>; return(this.identifier.CompareTo(n.identifier)); }
//Creates and unweights and undirected connection between nodes a and b public void addConnection(NodeMx <T> a, NodeMx <T> b) { EdgeMx <T> edgeA = new EdgeMx <T>(a, b, uniqueEdgeID); EdgeMx <T> edgeB = new EdgeMx <T>(b, a, uniqueEdgeID); edges.Add(edgeA); a.addEdge(edgeA); b.addEdge(edgeB); edgeCount = edges.Count; uniqueEdgeID++; }
public static List <NodeMx <int> > DFS(GraphMx <int> G, int startNode) { List <NodeMx <int> > foundNodes = new List <NodeMx <int> >(); NodeMx <int> s = G.nodes[startNode]; s.isVisited = true; foundNodes.Add(s); for (int n = 0; n < s.nodeEdges.Count; n++) { NodeMx <int> v = s.nodeEdges[n].nodes[1]; if (v.isVisited == false) { v.isVisited = true; List <NodeMx <int> > foundNodesTemp = DFS(G, v.identifier); foundNodes.AddRange(foundNodesTemp); } } return(foundNodes); }
public static double[] DijkstraShortestPath(GraphMx <int> G, int S, out List <NodeMx <int> >[] paths) { double[] shortestPaths = new double[G.nodeCount]; paths = new List <NodeMx <int> > [G.nodeCount]; //Set all the initials shortest paths to basically infinity and then reassign them to an //initial value of -1 for the nodes that are reachable for (int n = 0; n < shortestPaths.Length; n++) { shortestPaths[n] = Double.MaxValue; } //First we need to figure out which nodes arent reachable from out starting node S. List <NodeMx <int> > ReachableNodes = BFS(G, S); for (int n = 0; n < ReachableNodes.Count; n++) { shortestPaths[ReachableNodes[n].identifier] = -1; } //During the process of the breadth first search (BFS) we will have set the "isVisited" flag to true //for each node which we now need to undo for (int n = 0; n < G.nodeCount; n++) { G.nodes[n].isVisited = false; } //Initialize the paths to unreachable nodes as null for (int n = 0; n < G.nodeCount; n++) { if (shortestPaths[n] > -1) { paths[n] = null; } else { paths[n] = new List <NodeMx <int> >(); paths[n].Add(G.nodes[S]); } } //Initialize our explored nodes with our starting node List <NodeMx <int> > exploredNodes = new List <NodeMx <int> >(); exploredNodes.Add(G.nodes[S]); G.nodes[S].isVisited = true; shortestPaths[S] = 0; while (exploredNodes.Count < ReachableNodes.Count) { //For each node we have explored List <EdgeMx <int> > edgesToConsider = new List <EdgeMx <int> >(); for (int n = 0; n < exploredNodes.Count; n++) { NodeMx <int> tempNodeTail = exploredNodes[n]; //Find all of its edges in the region which we have not yet explored for (int m = 0; m < tempNodeTail.nodeEdges.Count; m++) { NodeMx <int> tempNodeHead = tempNodeTail.nodeEdges[m].nodes[1]; if (tempNodeHead.isVisited == false) { edgesToConsider.Add(tempNodeTail.nodeEdges[m]); } } } //Now that we have the list of candidate edges we need to compute the Dijkstra criteria for each edge EdgeMx <int> nextEdge = edgesToConsider[0]; double DijstraMin = Double.MaxValue; double tempDijkstra; for (int n = 0; n < edgesToConsider.Count; n++) { tempDijkstra = shortestPaths[edgesToConsider[n].nodes[0].identifier] + edgesToConsider[n].weight; if (tempDijkstra < DijstraMin) { DijstraMin = tempDijkstra; nextEdge = edgesToConsider[n]; } } //Now that we have found the edge that minimizes the Dijkstra criteria we will add the node at the //head of the edge to the list of explored nodes and update its shortest path length and shortest //path in our other variables NodeMx <int> nodeToAdd = nextEdge.nodes[1]; nodeToAdd.isVisited = true; exploredNodes.Add(nodeToAdd); //The shortest path of the node we are going to add is equal to the shortest path of the node from which we //came from plus the weight of the edge shortestPaths[nodeToAdd.identifier] = shortestPaths[nextEdge.nodes[0].identifier] + nextEdge.weight; List <NodeMx <int> > pathUptillNow = paths[nextEdge.nodes[0].identifier]; for (int n = 1; n < pathUptillNow.Count; n++) { paths[nodeToAdd.identifier].Add(pathUptillNow[n]); } paths[nodeToAdd.identifier].Add(nodeToAdd); } return(shortestPaths); }
//Default constructor for the undirected and unweighted case public EdgeMx(NodeMx <T> a, NodeMx <T> b, int i) { nodes[0] = a; nodes[1] = b; identifier = i; }