diff --git a/04. Trees and graphs/4.1. route_between_nodes.java b/04. Trees and graphs/4.1. route_between_nodes.java new file mode 100644 index 0000000..f839d0a --- /dev/null +++ b/04. Trees and graphs/4.1. route_between_nodes.java @@ -0,0 +1,66 @@ +import java.util.LinkedList; + +public class Question { + public enum State { + Unvisited, Visited, Visiting; + } + + public static void main(String a[]) + { + Graph g = createNewGraph(); + Node[] n = g.getNodes(); + Node start = n[3]; + Node end = n[5]; + System.out.println(search(g, start, end)); + } + + public static Graph createNewGraph() + { + Graph g = new Graph(); + Node[] temp = new Node[6]; + + temp[0] = new Node("a", 3); + temp[1] = new Node("b", 0); + temp[2] = new Node("c", 0); + temp[3] = new Node("d", 1); + temp[4] = new Node("e", 1); + temp[5] = new Node("f", 0); + + temp[0].addAdjacent(temp[1]); + temp[0].addAdjacent(temp[2]); + temp[0].addAdjacent(temp[3]); + temp[3].addAdjacent(temp[4]); + temp[4].addAdjacent(temp[5]); + for (int i = 0; i < 6; i++) { + g.addNode(temp[i]); + } + return g; + } + + public static boolean search(Graph g, Node start, Node end) { + LinkedList q = new LinkedList(); + for (Node u : g.getNodes()) { + u.state = State.Unvisited; + } + start.state = State.Visiting; + q.add(start); + Node u; + while(!q.isEmpty()) { + u = q.removeFirst(); + if (u != null) { + for (Node v : u.getAdjacent()) { + if (v.state == State.Unvisited) { + if (v == end) { + return true; + } else { + v.state = State.Visiting; + q.add(v); + } + } + } + u.state = State.Visited; + } + } + return false; + } +} \ No newline at end of file diff --git a/04. Trees and graphs/4.1. route_between_nodes.md b/04. Trees and graphs/4.1. route_between_nodes.md new file mode 100644 index 0000000..3f4ce73 --- /dev/null +++ b/04. Trees and graphs/4.1. route_between_nodes.md @@ -0,0 +1,74 @@ +# 4.1. Route between nodes + +> Given a directed graph and two nodes (S and E), is there a route from S to E? + +A graph can be written like this: + +```java +class Graph { + public Node[] nodes; +} + +class Node { + public String name; + public Node[] children; +} +``` + +The function to find a route from S to E: + +```java +bool findRoute(Node S, Node E) { + Node[] children = S.children; + for (int i = 0; i < children.size(); i++){ + if (children[i] == E) { + return True; + } + if (children[i].children == Null) { + continue; + } + else if (findRoute(Node children[i].children, E)){ + return True; + } + } + return False; +} +``` + +Example, Route from 5 to 11: + +* 5 + * 2 + * 3 + * 4 + * 1 + * 9 + * 11 + * 6 + +1. children = [2, 1, 6] + 1. Recursive of 2, children = [3, 4] + 2. None of them have children, continue, return False +2. Back to main loop, continue with children + 1. recursive of 1, children = [9, 11] + 2. found in children[1] == E, return True +3. Back to main loop, return True + +Looks good, O(N) where N = all elements in graph, well if the graph isn't balanced at all we might have to iterate through it all. + +## Hints + +Two well known algorithms can do this, what are the tradeoffs between them? + +1. Depth-first search (mine) + 1. Check each node until the end +2. Breadth-first search + 1. Cheack each main children first, then go deep + +## Solution + +Remember to **mark the found nodes as visited to avoid cycles and repetitions of nodes**. + +For an iterative solution of breadh-first search, see Java files. + +Depth-first search is a bit simpler to implement since it can be done with simple recursion. Breadth-first search can also be useful to find the shortest path, whereas depth-first search might traverse one adjacent node very deeply before ever going onto the immediate neighbors. diff --git a/04. Trees and graphs/Graph.java b/04. Trees and graphs/Graph.java new file mode 100644 index 0000000..2453127 --- /dev/null +++ b/04. Trees and graphs/Graph.java @@ -0,0 +1,22 @@ +public class Graph { + public static int MAX_VERTICES = 6; + private Node vertices[]; + public int count; + public Graph() { + vertices = new Node[MAX_VERTICES]; + count = 0; + } + + public void addNode(Node x) { + if (count < vertices.length) { + vertices[count] = x; + count++; + } else { + System.out.print("Graph full"); + } + } + + public Node[] getNodes() { + return vertices; + } +} \ No newline at end of file diff --git a/04. Trees and graphs/Node.java b/04. Trees and graphs/Node.java new file mode 100644 index 0000000..02fb930 --- /dev/null +++ b/04. Trees and graphs/Node.java @@ -0,0 +1,26 @@ +class Node { + private Node adjacent[]; + public int adjacentCount; + private String vertex; + public Question.State state; + public Node(String vertex, int adjacentLength) { + this.vertex = vertex; + adjacentCount = 0; + adjacent = new Node[adjacentLength]; + } + + public void addAdjacent(Node x) { + if (adjacentCount < adjacent.length) { + this.adjacent[adjacentCount] = x; + adjacentCount++; + } else { + System.out.print("No more adjacent can be added"); + } + } + public Node[] getAdjacent() { + return adjacent; + } + public String getVertex() { + return vertex; + } +} \ No newline at end of file