Issue passing argument to my main using DFS - Java - java

I am trying to get this code running as fast as possible when traversing through my stack of my DFS currently the input files are like so:
0 2
2 1
1 4
4 5
5 6
10 8
8 9
9 6
7 6
3 4
0 1
3 9
0 4
Where my Maze class will tie the numbers together and create a graph for me. After the graph is created my DFS class runs through traversing giving one or all solutions to the .txt file submitted.I have recently altered my Maze class as for it to run more efficiently but am being thrown errors and the data is parsing through to my DFS to be outputted. My Maze class is as follows:
import java.io.*;
import java.util.*;
public class Maze {
private final Map<Integer, Set<Integer>> adjList = new HashMap<>();
/**
* The main constructor that takes a String for reading maze file.
*
* #param file
*/
public Maze(File file) throws FileNotFoundException {
try (Scanner scan = new Scanner(file)) {
while (scan.hasNextInt()) {
int node1 = scan.nextInt();
int node2 = scan.nextInt();
this.connect(node1, node2);
this.connect(node2, node1);
}
}
}
/**
* Makes a unidirectional connection from node1 to node2.
*/
private void connect(int node1, int node2) {
if (!this.adjList.containsKey(node1)) {
this.adjList.put(node1, new HashSet<Integer>());
}
this.adjList.get(node1).add(node2);
}
/**
* Returns a human-readable description of the adjacency lists.
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Map.Entry<Integer, Set<Integer>> adj : this.adjList.entrySet()) {
int from = adj.getKey();
Set<Integer> to = adj.getValue();
s.append(from).append(" connected to ").append(to).append('\n');
}
return s.toString();
}
/**
* Returns the set of nodes connected to a particular node.
*
* #param node - the node whose neighbors should be fetched
*/
public Iterable<Integer> getadjList(int node) {
return Collections.unmodifiableSet(adjList.get(node));
}
/**
* Demonstration of file reading.
*/
public static void main(String[] args) throws FileNotFoundException {
System.err.print("Enter File: ");
Scanner scanFile = new Scanner(System.in);
String file = scanFile.nextLine();
Maze m = new Maze(new File(file));
System.out.println(m);
}
}
And my DFS looks like so.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Stack;
public class DFS {
//starting node, the route to the next node, has node been visited
private int startNode;
private int[] route;
private boolean[] visited;
// 2 main arguments - Maze File & user input
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.node];
visited = new boolean[maze.node];
//Takes user's input and runs desired function
if(inputInt == 1){
findOne(maze, startNode, goalNode);
}
else if (inputInt == 2){
findAll(maze, startNode, goalNode);
}
else {
System.out.println("input invalid. No Solution Returned");
}
}
//Put path to goal in the stack
public Stack<Integer> route(int toGoalNode) {
if (!visited[toGoalNode]) {
return null;
}
Stack<Integer> pathStack = new Stack<Integer>();
for (int routeGoalNode = toGoalNode; routeGoalNode != startNode; routeGoalNode = route[routeGoalNode]) {
pathStack.push(routeGoalNode);
}
pathStack.push(startNode);
reverseStack(pathStack);
return pathStack;
}
//Reverse the stack
public void reverseStack(Stack<Integer> stackToBeReverse) {
if (stackToBeReverse.isEmpty()) {
return;
}
int bottom = popBottomStack(stackToBeReverse);
reverseStack(stackToBeReverse);
stackToBeReverse.push(bottom);
}
//Pop the bottom of the stack
private int popBottomStack(Stack<Integer> stackToBeReverse) {
int popTopStack = stackToBeReverse.pop();
if (stackToBeReverse.isEmpty()) {
return popTopStack;
} else {
int bottomStack = popBottomStack(stackToBeReverse);
stackToBeReverse.push(popTopStack);
return bottomStack;
}
}
//performs DFS and unsets visited to give the result of all paths
private void findAll(Maze maze, int node, int goal) {
visited[node] = true;
if(node == goal) {
printPath(goal);
} else {
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route[con] = node;
findAll(maze, con, goal);
}
}
}
visited[node] = false;
}
//performs DFS and maintains visited marker giving only one path
private void findOne(Maze maze, int node, int goal) {
visited[node] = true;
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route[con] = node;
findOne(maze, con, goal);
}
}
}
//Traverse the connections to the goal and print the path taken
public void printPath( int toGoal) {
int goalNode = 1;
if (visited[toGoal]) {
System.out.println("Completed Path: ");
for (int t : route(toGoal)) {
if (t == toGoal) {
System.out.print(t);
} else {
System.out.print(t + " -> ");
}
}
System.out.println();
}
}
public static void main(String[] args) throws FileNotFoundException {
Scanner scanFile = new Scanner(System.in);
int goalNode = 1;
System.out.print("Enter maze file: ");
String file = scanFile.nextLine();
Maze maze = new Maze(new File(file));
Scanner scanInt = new Scanner(System.in);
System.out.print("Enter desired feedback (1 = one soultion, 2 = all): ");
int inputInt = scanInt.nextInt();
// maze.toString();
System.out.println(maze);
DFS dfs = new DFS(maze, inputInt);
dfs.printPath(goalNode);
}
}
I've been looking over it for a while and can't figure out exactly why the data is parsing and being used. Ive altered a few things here and there but have been thrown even more errors. They specifically say
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at DFS.findOne(DFS.java:90)
at DFS.<init>(DFS.java:22)
at DFS.main(DFS.java:127)
Referencing to the lines of code:
visited[node] = true;
findOne(maze, startNode, goalNode);
DFS dfs = new DFS(maze, inputInt);
Now essentially im lead to believe that there is no argument being passed, if someone could pin point the problem and lend a hand in helping me out it would be greatly appreciated. Thanks again
EDIT:: Old version of Maze class
import java.io.*;
import java.util.*;
public class Maze {
static Set<Integer> Nodes = new HashSet<Integer>();
List<Integer>[] conList;
int node; //declaring value for my nodes.
int con; // declaring a connection
//Constructor takes an int parameter to read through the list of corresponding nodes
Maze(int node) {
this.node = node;
this.con = 0;
conList = (List<Integer>[]) new List[node];
for (int index = 0; index < node; index++) {
conList[index] = new LinkedList<Integer>();
}
}
//Constructor that takes a String of the maze file
public Maze(String mazeFile) {
this(nodeSize(mazeFile));
Scanner scan;
try {
//Creates a scanner for reading the file and loops through linking the nodes to their connections.
scan = new Scanner(new File(mazeFile));
while (scan.hasNextInt()) {
int firstNode = scan.nextInt();
int secondNode = scan.nextInt();
addCon(firstNode, secondNode);
}
} catch (FileNotFoundException ex) {
System.out.println("File Not Found.");
}
}
/*Takes String parameter which is the name of the maze file.
* Method designed to return the the size of the set of nodes
*/
public static int nodeSize(String mazeFile) {
Scanner scanNodeSize;
try {
scanNodeSize = new Scanner(new File(mazeFile));
//while scan has more int's left repeat.
while (scanNodeSize.hasNextInt()) {
int firstNode = scanNodeSize.nextInt();
int secondNode = scanNodeSize.nextInt();
Nodes.add(firstNode);
Nodes.add(secondNode);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return Nodes.size();
}
//Method designed to connect the first and second nodes
private void addCon(int firstNode, int secondNode) {
con++;
conList[firstNode].add(secondNode);
conList[secondNode].add(firstNode);
}
//outputs the nodes and their connection's (#remove later?)
public void print() {
for (int n = 0; n < node; n++) {
System.out.print(n + " connected to ");
for (int w : conList[n]) {
System.out.print(w + " ");
}
System.out.println();
}
}
//method returns a list, enabling nodes to be easily accessible.
public Iterable<Integer> getconList(int nodes) {
return conList[nodes];
}
}

You are getting an index out of bounds exception at 0. This should lead you to believe that the array has not properly been initialized. You initialize the visited[] array with maze.node however nowhere in your code do we see where this node variable is located. You need to give a proper value to maze.node if you want this to even be runnable.
*EDIT - My above answer is no longer applicable now that we have your previous Maze class which explains why the code will not run.
There are so many things wrong with the code in its current state so I will try and give you some direction here:
Your new way of creating a Maze is to read from the file and connect the 2 points and store them in an Map. The issue with this is that you cannot just get the next element since you have to have the key to get the element. To fix this you should use a different data structure.
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.node]; //!!! maze.node isn't a thing anymore
visited = new boolean[maze.node]; //!!! maze.node isn't a thing anymore
You can see that you are trying to access maze.node which use to be a variable of Maze. It no longer is. You need to find a new way of getting a node from Maze. To do this you need to grab the node from your data structure in a different way:
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.adjList.getNode()];
visited = new boolean[maze.adjList.getNode()];
You have a lot of options for a different data structure for you adjacency list but something such as this:
http://theoryofprogramming.com/adjacency-list-in-java/
will give you a decent starting point.

Related

Creating a more concise traversal of a stack for DFS algorithm - Java [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I am trying to get this code running as fast as possible when traversing through my stack of my DFS currently the input files are like so:
0 2
2 1
1 4
4 5
5 6
10 8
8 9
9 6
7 6
3 4
0 1
3 9
0 4
Where my Maze class will tie the numbers together and create a graph for me. After the graph is created my DFS class runs through traversing giving one or all solutions to the .txt file submitted. My DFS class looks like so:
import java.util.Scanner;
import java.util.Stack;
public class DFS {
//starting node, the route to the next node, has node been visited
private int startNode;
private int[] route2;
private boolean[] visited;
// 2 main arguments - Maze File & user input
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goal = 1;
route2 = new int[maze.node];
visited = new boolean[maze.node];
if(inputInt == 1){
startDFSone(maze, startNode, goal);
}
else if (inputInt == 2){
startDFSall(maze, startNode, goal);
}
else {
System.out.println("input invalid. No Solution Returned");
}
}
//Put path to goal in the stack
public Stack<Integer> route2(int toGoalNode) {
if (!visited[toGoalNode]) {
return null;
}
Stack<Integer> pathStack = new Stack<Integer>();
for (int route2GoalNode = toGoalNode; route2GoalNode != startNode; route2GoalNode = route2[route2GoalNode]) {
pathStack.push(route2GoalNode);
}
pathStack.push(startNode);
reverseStack(pathStack);
return pathStack;
}
//Reverse the stack
public void reverseStack(Stack<Integer> stackToBeReverse) {
if (stackToBeReverse.isEmpty()) {
return;
}
int bottom = popBottomStack(stackToBeReverse);
reverseStack(stackToBeReverse);
stackToBeReverse.push(bottom);
}
//Pop the bottom of the stack
private int popBottomStack(Stack<Integer> stackToBeReverse) {
int popTopStack = stackToBeReverse.pop();
if (stackToBeReverse.isEmpty()) {
return popTopStack;
} else {
int bottomStack = popBottomStack(stackToBeReverse);
stackToBeReverse.push(popTopStack);
return bottomStack;
}
}
//performs DFS and unsets visited to give the result of all paths
private void startDFSall(Maze maze, int node, int goal) {
visited[node] = true;
if(node == goal) {
printPath(goal);
} else {
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route2[con] = node;
startDFSall(maze, con, goal);
}
}
}
visited[node] = false;
}
//performs DFS and maintains visited marker giving only one path
private void startDFSone(Maze maze, int node, int goal) {
visited[node] = true;
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route2[con] = node;
startDFSone(maze, con, goal);
}
}
}
//Traverse the connections to the goal and print the path taken
public void printPath( int toGoal) {
int goalNode = 1;
if (visited[toGoal]) {
System.out.println("Completed Path: ");
for (int t : route2(toGoal)) {
if (t == toGoal) {
System.out.print(t);
} else {
System.out.print(t + " -> ");
}
}
System.out.println();
}
}
/**
*
* #param args
*/
public static void main(String[] args) {
Scanner scanFile = new Scanner(System.in);
int goalNode = 1;
System.out.print("Enter maze file: ");
String file = scanFile.nextLine();
Maze maze = new Maze(file);
Scanner scanInt = new Scanner(System.in);
System.out.print("Enter desired feedback (1 = one soultion, 2 = all): ");
int inputInt = scanInt.nextInt();
maze.print();
System.out.println();
DFS dfs = new DFS(maze, inputInt);
dfs.printPath(goalNode);
}
}
I am asking for some example or pointers to get my code (specifically the traversal of the stack) more concise so that when I implement my testing for completion time of the code I can minimize it as much as humanly possible.
I'll link my Maze class below if it might help. Thanks.
import java.io.*;
import java.util.*;
public class Maze {
final static Set<Integer> Nodes = new HashSet<Integer>();
List<Integer>[] adjList;
int node; //declaring value for my nodes.
int con; // declaring a connection
/**
* This constructors takes an integer parameter for reading node indexes in
* a list of adjacent nodes.
*
* #param node - integer parameter for passing the nodes value from the file
* and create a list of adjacent nodes.
*/
Maze(int node) {
this.node = node;
this.con = 0;
adjList = (List<Integer>[]) new List[node];
for (int index = 0; index < node; index++) {
adjList[index] = new LinkedList<Integer>();
}
}
/**
* The main constructor that takes a String for reading maze file.
*
* #param mazeFile
*/
public Maze(String mazeFile) {
this(getNodeSize(mazeFile));
Scanner scan;
try {
//Creates a scanner for reading the file and loops through linking the nodes to their connections.
scan = new Scanner(new File(mazeFile));
while (scan.hasNextInt()) {
int node1 = scan.nextInt();
int node2 = scan.nextInt();
addCon(node1, node2);
}
} catch (FileNotFoundException ex) {
System.out.println("File Not Found.");
}
}
/**
* This method returns a size of the set of nodes by taking a String
* parameter which the name of the maze file.
*
* #param mazeFile - String parameter for reading maze file for scanning the
* size of the nodes.
* #return - returns an integer value for the size of the set of nodes.
*/
public static int getNodeSize(String mazeFile) {
Scanner scanNodeSize;
try {
scanNodeSize = new Scanner(new File(mazeFile));
while (scanNodeSize.hasNextInt()) {
int node1 = scanNodeSize.nextInt();
int node2 = scanNodeSize.nextInt();
Nodes.add(node1);
Nodes.add(node2);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return Nodes.size();
}
/**
* This method adds an con by adding two different nodes in array of list
* called adjacency list.
*
* #param node1 - first node.
* #param node2 - next node.
*/
private void addCon(int node1, int node2) {
con++; //Increase con by one whenever this addcon method is called.
adjList[node1].add(node2);
adjList[node2].add(node1);
}
/**
* Print the nodes and its cons by looping through the adjacency list.
*/
public void print() {
for (int n = 0; n < node; n++) {
System.out.print(n + " connected to ");
for (int w : adjList[n]) {
System.out.print(w + " ");
}
System.out.println();
}
}
/**
* This method returns a list of nodes to allow objects to be the target for
* "for-each" statement.
*
* #param nodes - an Integer parameter for getting the number of nodes in a
* list.
* #return - returns a list of nodes.
*/
public Iterable<Integer> getadjList(int nodes) {
return adjList[nodes];
}
/**
* Unit testing To test if it reads the file.
*
* #param args
*/
public static void main(String[] args) {
System.out.print("Enter File: ");
Scanner scanFile = new Scanner(System.in);
String file = scanFile.nextLine();
Maze M = new Maze(file);
M.print();
}
}
Also any general input would be fantastic.

Returning a value from a method and using it in another class - Java

Currently in my Maze class I have two methods
public Set<Integer> getNode(int node) {
return Collections.unmodifiableSet(adjList.get(node));
}
and
public int getNumberOfNodes() {
return adjList.size();
}
I am trying to pull through my current node into my DFS class but I seem to be missing something. Currently with my DFS class I have this.
private int[] route;
private boolean[] visited;
public DFS(Maze maze, int input) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.getadjList(node)]; << errors here
visited = new boolean[maze.adjList.getNode()]; << errors here
//Takes user's input and runs desired function
if(input == 1){
findOne(maze, startNode, goalNode);
}
else if (input == 2){
findAll(maze, startNode, goalNode);
}
else {
System.out.println("input invalid. No Solution Returned");
}
}
Feel free to ask me anything if I can help. Thanks
Full Maze class if needed:
import java.io.*;
import java.util.*;
public class Maze {
final Map<Integer, Set<Integer>> adjList = new HashMap<>();
/**
* The main constructor that takes a String for reading maze file.
*
* #param file
*/
public Maze(File file) throws FileNotFoundException {
try (Scanner scan = new Scanner(file)) {
while (scan.hasNextInt()) {
int node1 = scan.nextInt();
int node2 = scan.nextInt();
this.connect(node1, node2);
this.connect(node2, node1);
}
}
}
/**
* Makes a unidirectional connection from node1 to node2.
*/
private void connect(int node1, int node2) {
if (!this.adjList.containsKey(node1)) {
this.adjList.put(node1, new HashSet<Integer>());
}
this.adjList.get(node1).add(node2);
}
/**
* Returns a human-readable description of the adjacency lists.
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Map.Entry<Integer, Set<Integer>> adj : this.adjList.entrySet()) {
int from = adj.getKey();
Set<Integer> to = adj.getValue();
s.append(from).append(" connected to ").append(to).append('\n');
}
return s.toString();
}
/**
* Returns the set of nodes connected to a particular node.
*
* #param node - the node whose neighbors should be fetched
*/
public Iterable<Integer> getadjList(int node) {
return Collections.unmodifiableSet(adjList.get(node));
}
public Set<Integer> getNode(int node) {
return Collections.unmodifiableSet(adjList.get(node));
}
public int getNumberOfNodes() {
return adjList.size();
}
/**
* Demonstration of file reading.
*/
public static void main(String[] args) throws FileNotFoundException {
System.err.print("Enter File: ");
Scanner scanFile = new Scanner(System.in);
String file = scanFile.nextLine();
Maze m = new Maze(new File(file));
System.out.println(m);
}
}
These statements look like they are trying to create a new int array and a new boolean array:
route = new int[maze.getadjList(node)]; << errors here
visited = new boolean[maze.adjList.getNode()]; << errors here
but to create an array the parameter between the square brackets must be an int.
Its value gives the size of the array.
The functions you are calling do not return ints, hence you get errors.
As #Ian Mc stated in the comments the problem was resolved by first initiating the arrays using.
route = new int[maze.getNumberOfNodes()]
visited = new boolean[ maze.getNumberOfNodes()]

Representing a Graph in Java

I am developing a maze system but not graphically maze system. The maze is actually referred as undirected graph I think because they don't direct to each other. The maze looks like this from a text file:
11 3
2 3
0 3
1 4
5 4
5 7
6 7
7 8
8 9
9 10
0 5
I don't know if I did was right to represent this in graph. If you check my code, it seems to be right, isn't it?
import java.io.*;
import java.util.Scanner;
class Arc {
public int nodeNo;
public Arc next;
public Arc(int nodeNo, Arc next) {
this.nodeNo = nodeNo;
this.next = next;
}
public String toString(){
return "" + nodeNo;
}
}
class Node {
int index;
Arc adjList;
Node(int index, Arc adjList) {
this.index = index;
this.adjList = adjList;
}
public String toString() {
return "" + index;
}
}
public class Maze {
Node[] stack;
private Scanner scan;
private static Scanner scan2;
public Maze(String mazeFile) throws FileNotFoundException {
scan = new Scanner(new File(mazeFile));
stack = new Node[12];
for (int n = 0; n < stack.length; n++) {
stack[n] = new Node(n, null);
}
while (scan.hasNext()) {
int v1 = indexForNode(scan.next());
int v2 = indexForNode(scan.next());
stack[v1].adjList = new Arc(v2, stack[v1].adjList);
stack[v2].adjList = new Arc(v1, stack[v2].adjList);
}
}
int indexForNode(String index) {
for (int n = 0; n < stack.length; n++) {
if (stack[n].index == Integer.parseInt(index)) {
return n;
}
}
return -1;
}
public void print(){
System.out.println();
for(int n = 0; n < stack.length; n++){
System.out.print(stack[n]);
for(Arc arc = stack[n].adjList; arc != null; arc = arc.next){
System.out.print(" --> " + stack[arc.nodeNo].index);
}
System.out.println("\n");
}
}
public static void main(String[] args) throws FileNotFoundException {
scan2 = new Scanner(System.in);
System.out.print("Enter maze file name: ");
String file = scan2.nextLine();
Maze maze = new Maze(file);
maze.print();
}
}
In general, I would say no: this is not a good approach. A basic graph, where the edges don't have weights, is implemented as a series of nodes with a Many ↔ Many relationship.
So basically your Node would look like this:
public class Node {
private List<Node> out;
}
See this question for more information.

Java: Why is my array of objects overwriting all the previous data inside a loop?

I try to make an array of nodes with a node on a specific place in the array.
For example:
I add a node in the array and set its number to 1.
I add another node in the array on the next position and set its number to 2.
Both nodes got the number 2 now.
Sample of the code:
public static String run(InputStream in) {
Scanner sc = new Scanner(in);
//indicating values
sc.nextInt(); /* int vertices = */
int edge = sc.nextInt();
int start = sc.nextInt();
int end = sc.nextInt();
if (start == end) {
sc.close();
Path = "yes";
} else {
nodes = new Node[edge + 1];
for (int i = 1; i < edge; i++) {
//Node values
int number = sc.nextInt();
int next = sc.nextInt();
sc.nextInt(); /* int distance = */
Node node = new Node(number, next);
if (nodes[number] == null) {
nodes[number] = (node);
} else {
nodes[number].addChild(next);
}
}
hasPath(nodes[start], end);
}
sc.close();
return Path;
}
Sample of the Node code:
import java.util.ArrayList;
public class Node {
private ArrayList<Integer> childs = new ArrayList<Integer>();
private static int number;
public Node(int n, int next){
number = n;
childs.add(next);
}
public int getNumber(){
return number;
}
public void addChild(int child){
childs.add(child);
}
Can anyone please help me?
The problem is with declaring the number member static. This means there's only one such member for the Node class, instead of each instance having its own member. Just define it as an instance variable, and you should be fine:
public class Node {
private ArrayList<Integer> childs = new ArrayList<Integer>();
private int number; // Note the static was removed
// rest of the class

File input for Dijkstra's algorithm

I am having trouble figuring out how to read an input file with java. The file has the following format:
u1 v1 w1
u2 v2 w2
...
um vm wm
-1
source
Each 3-tuple denotes an edge, which is specified by its source-vertex, its destination-vertex, and its weight (example: newyork boston 30). The description of the graph is terminated by a “flag”, the integer -1. A string follows this flag; this string is the name of the source vertex for the Dijkstra shortest-path algorithm. That is, you are to determine and print out the shortest path from this source vertex to every other vertex in the graph.
Here is my current work.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Vertex implements Comparable<Vertex> {
public final String name;
public Edge[] adjacencies;
public double minDistance = Double.POSITIVE_INFINITY;
public Vertex previous;
public Vertex(String argName) {
name = argName;
}
public String toString() {
return name;
}
public int compareTo(Vertex other) {
return Double.compare(minDistance, other.minDistance);
}
}
class Edge {
public final Vertex target;
public final double weight;
public Edge(Vertex argTarget, double argWeight) {
target = argTarget;
weight = argWeight;
}
}
public class Dijkstra {
public static void computePaths(Vertex source) {
source.minDistance = 0.;
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex u = vertexQueue.poll();
// Visit each edge exiting u
for (Edge e : u.adjacencies) {
Vertex v = e.target;
double weight = e.weight;
double distanceThroughU = u.minDistance + weight;
if (distanceThroughU < v.minDistance) {
vertexQueue.remove(v);
v.minDistance = distanceThroughU;
v.previous = u;
vertexQueue.add(v);
}
}
}
}
public static ArrayList<Vertex> getShortestPathTo(Vertex target) {
ArrayList<Vertex> path = new ArrayList<Vertex>();
for (Vertex vertex = target; vertex != null; vertex = vertex.previous)
path.add(vertex);
Collections.reverse(path);
return path;
}
public String[] readFile(String fileName) throws FileNotFoundException {
Scanner input = new Scanner(new File(fileName));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split("");
return graph;
}
public static void main(String[] args) throws FileNotFoundException {
final String TEST = "/TestInput.txt";
Scanner input = new Scanner(new File(TEST));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split(" ");
for (int i = 0; i < graph.length; i++) {
System.out.println(graph[i]);
}
Vertex[] verts = new Vertex[graph.length];
Edge[] edges = new Edge[graph.length];
Vertex v1 = new Vertex("");
Vertex v2 = new Vertex("");
Vertex source = new Vertex("");
int count = 0;
outerloop: for (int i = 0; i < (graph.length); i++) {
if (graph[i].equals("-1")) {
// do algorithm initialization here w/ source
}
if (i == 0) {
verts[i] = new Vertex(graph[i]);
count++;
} else {
innerloop: for (int j = count; j >= 0; j--) {
if (i / 3 == 0) {
if (graph[i].equals(verts[j].toString())) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v1 = verts[count];
count++;
}
}
if (i / 3 == 1) {
if (graph[i].equals(verts[j])) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v2 = verts[count];
count++;
}
}
if (i / 3 == 2) {
}
}
}
}
for (int i = 0; i < verts.length; i++) {
System.out.println(verts[i]);
}
}
}
So my only problem is how to get from the given .txt file format to a graph. Any suggestions are welcome.
Use a Scanner to parse the file data. For each tuple, if the source vertex hasn't been created, create it, otherwise find it in the pre-existing graph -- create a search function. Do the same for the target vertex. Next, create an edge with a weight equal to the third token in the tuple, and add the target vertex to the edge. Finally, add the edge to the adjacency list of the source vertex.
For the previously mentioned search function, you can implement something that can search through each vertex of the graph starting from any vertex. Recursion will be necessary.
public static Vertex search(Vertex src, String name);
A simpler solution is to keep a list of all the vertices you create as your constructing the graph and search through that.
public static Vertex search(List<Vertex> vertices, String name);
When your done constructing the graph and you have the name of the vertex where Dijkstra's algorithm will begin, you can use the search function to get a reference to the vertex.
Dijkstra.computePath(search(vertices, startVertexName));
And, that's it. Here's an example of how to parse your file data:
List<Vertex> vertices = new ArrayList<Vertex>();
String src =
"Pittsburgh Philadelphia 323 "+
"Pittsburgh Ohio 125 "+
"Ohio Philadelphia 400 "+
"-1 Ohio";
//new Scanner(new File(fileName));
Scanner scnr = new Scanner(src);
String src, target;
int weight;
while(scnr.hasNext())
{
src = scnr.next();
if(src.equals("-1"))
break;
else {
target = scnr.next();
weight = scnr.nextInt();
}
//call search(), implement logic in addToGraph()
addVertexToGraph(src, target, weight, vertices);
}
String startVertexName = scnr.next();
scnr.close();
Note that Scanner.next returns the next token separated by white space (the default delimiter), so your file data must be formatted that way.
Here's a shot:
/**
* Read the file using provided filename, construct vertices etc.
*
* #param fileName name of the file to read.
* #return true if everything is OK
* #throws FileNotFoundException if file is not found or not readable
*/
public boolean readFile(final String fileName) throws FileNotFoundException {
final Scanner input = new Scanner(new File(fileName));
boolean result = false;
while (input.hasNext()) {
final String line = line = input.nextLine();
if ("-1".equals(line)) {
// end of data
if (input.hasNext()) {
final String nameOfTheSource = input.next();
// TODO: do something with nameOfTheSource
result = true;
} else {
// bad input format: there should be something after -1
}
} else {
final String Scanner vert = new Scanner(line);
try {
final String sourceName = vert.next();
final String targetName = vert.next();
final int weight = vert.nextInt(); // assuming int for weight
// TODO: create Vertices and Edge here
} catch (final NoSuchElementException ex) {
// bad input format for "line"!
}
}
}
return result;
}
Not tested.
{import Stack.Dijkstra;
{import java.io.File;
{import java.io.FileNotFoundException;
{import java.util.Scanner;
{public class App {
{public static void main(String[] args) throws {FileNotFoundException {
{Vertex v1 = new Vertex("A");
{Vertex v2 = new Vertex("B");
{Vertex v3 = new Vertex("C");
{`v1.addNeighbour(new Edge(1, v1, v2));
{`v1.addNeighbour(new Edge(10, v1, v2));
{`v2.addNeighbour(new Edge(1, v2, v3));
{`Dijkstra dijkstra = new Dijkstra();
{`dijkstra.computePath(v1);
{`System.out.println(dijkstra.getShortestPathTo(v3));
{`final String test = "X:\\neon3\\eclipse\\TestInput.txt";
{`Scanner input = new Scanner(new File(test));
{`String line = "";
{`while (input.hasNext()) {
{`line = line.concat(input.nextLine());
}
{`String[] graph = line.split(" ");
{`for (int i = 0; i < graph.length; i++) {
{`System.out.println(graph[i]);
}
}
}`}

Categories

Resources