4.1. route between nodes in graph
This commit is contained in:
parent
2a40eebc1c
commit
0b23f63b46
|
|
@ -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<Node> q = new LinkedList<Node>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue