I have a problem with the implementation of the breadth-first search algorithm, I have a method that gives me an array of integers from 0-8, in random order. I also have an integer m that tells me which number is blank. Here are the rules:
I get a block of numbers, like:
456
782
301
And lets say that 8 is the blank value, I can swap it with 5, 7, 2, and 0. since they are directly next to it. I have to use breadth-first search to solve this puzzle. Here is the code I have written so far:
package application;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Vector;
public class Solution {
/******************************************
* Implementation Here
***************************************/
/*
* Implementation here: you need to implement the Breadth First Search
* Method
*/
/* Please refer the instruction document for this function in details */
public static LinkedHashSet<int[]> OPEN = new LinkedHashSet<int[]>();
public static HashSet<int[]> CLOSED = new HashSet<int[]>();
public static boolean STATE = false;
public static int empty;
public static void breadthFirstSearch(int[] num, int m, Vector solution1) {
int statesVisited = 0;
for(int i : num) {
if(num[i] == m) {
empty = i;
}
}
int[] start = num;
int[] goal = {0,1,2,3,4,5,6,7,8};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (compareArray(X,goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null)
OPEN.add(temp);
temp = left(X, pos);
if (temp != null)
OPEN.add(temp);
temp = down(X, pos);
if (temp != null)
OPEN.add(temp);
temp = right(X, pos);
if (temp != null)
OPEN.add(temp);
if(OPEN.isEmpty())
System.out.println("Ending loop");
}
}
}
public static boolean compareArray(int[] a, int[] b) {
for(int i: a)
if(a[i] != b[i])
return false;
return true;
}
public static int[] up(int[] s, int p) {
int[] str = s;
if (p > 3) {
int temp = str[p-3];
str[p-3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] down(int[] s, int p) {
int[] str = s;
if (p < 6) {
int temp = str[p+3];
str[p+3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] left(int[] s, int p) {
int[] str = s;
if (p != 0 && p != 3 && p != 6) {
int temp = str[p-1];
str[p-1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] right(int[] s, int p) {
int[] str = s;
if (p != 2 && p != 5 && p != 8) {
int temp = str[p+1];
str[p+1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
This code just immediately ends, and never finds an answer. Perhaps I have done something wrong? Please help.
Please Note: This is my first question on StackOverFlow, so if anyone has any criticisms please tell me and I will fix them right away.
First of all, you have a parameter which isn't doing anything, Vector solution in:
public static void breadthFirstSearch(int[] num, int m, Vector solution1)
Also you are passing in the position of the zero element which you are representing as m, then assigning a local variable to that position, seems a little pointless to me there's no need to pass in the zero position if you're going to search for it anyway.
Updated breadth first search method:
public static void breadthFirstSearch(int[] num) {
for (int i : num) {
if (num[i] == 0) {
empty = i;
}
}
int[] start = num;
int[] goal = {1, 2, 3, 4, 5, 6, 7, 8, 0};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (Arrays.equals(X, goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = left(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = down(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = right(X, pos);
if (temp != null) {
OPEN.add(temp);
}
if (OPEN.isEmpty()) {
System.out.println("Ending loop");
}
}
}
}
The main issue with your program was that within your movement methods up(), down(), left(), right(). You weren't creating complete copies of the arrays, thus resulting in modifications happening to the original array.
Thus this assignment:
int[] str = s;
must be changed to:
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
Here's an example of a completed method:
public static int[] up(int[] s, int p) {
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
if (p > 3) {
int temp = str[p - 3];
str[p - 3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && !CLOSED.contains(str)) {
return str;
} else {
return null;
}
}
SIDE NOTE (Not essential):
There are certain permutations of the array which won't result in the goal state. This puzzle itself can have a total number of 9! configurations, but actually only 9!/2 of these are solvable.
I wrote an algorithm for checking the parity of the puzzle, which can be done as a kind of preprocessing, I used it in order to create random instances for testing the data.
public boolean isSolvable(int[] puzzle) {
boolean parity = true;
int gridWidth = (int) Math.sqrt(puzzle.length);
boolean blankRowEven = true; // the row with the blank tile
for (int i = 0; i < puzzle.length; i++) {
if (puzzle[i] == 0) { // the blank tile
blankRowEven = (i / gridWidth) % 2==0;
continue;
}
for (int j = i + 1; j < puzzle.length; j++) {
if (puzzle[i] > puzzle[j] && puzzle[j] != 0) {
parity = !parity;
}
}
}
// even grid with blank on even row; counting from top
if (gridWidth % 2 == 0 && blankRowEven) {
return !parity;
}
return parity;
}
For the vector
You want to be able to print out the path that has been taken to get to the goal state, I would recommend having a class for the State such:
private State previousState;
private int[] current;
public State(int[] current, State previousState) {
this.current = current;
this.previousState = previousState
}
public State getPreviouState(){
return previousState;
}
public int[] getCurrentState(){
return currentState;
}
Then when you have the goal State you can loop through all the previous States to see the path it took.
State current = GOAL;
while(current != null){
System.out.println(Arrays.toString(current));
current = current.getPreviousState();
}
The method up(...) has an error:
You have:
str[p] = str[p-3];
Which I'm guessing should be:
str[p] = temp;
Related
I am trying to implement a max priority queue using a heap binary tree with a triple-linked node. This is the code that I currently have yet when I run it and try to print out the tree nothing prints out it is just empty lines. I am using the helped methods sink and swim in order to help me organize the queue as I add different elements. I am also implementing an ADT (MaxPQ) which just has the public methods that need to be implemented. I was wondering if there is anything that I am doing wrong?
public class LinkedMaxPQ<T extends Comparable<T>> implements MaxPQ<T> {
// Instance variables
Node root;
int size;
Node lastInserted;
// Node inner class definition
// Node class
class Node {
int N;
T info;
Node left;
Node right;
Node parent;
Node(T info, int N) {
this.info = info; this.N = N;
}
}
private void swim(Node x){
if(x == null) return;
if(x.parent == null) return; // we're at root
int cmp = x.info.compareTo(x.parent.info);
if(cmp > 0){
swapNodeData(x, x.parent);
swim(x.parent);
}
}
private void swapNodeData(Node x, Node y){
T temp = x.info;
x.info = y.info;
y.info = temp;
}
private void sink(Node x){
if(x == null) return;
Node swapNode;
if(x.left == null && x.right == null){
return;
}
else if(x.left == null){
swapNode = x.right;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else if(x.right == null){
swapNode = x.left;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else{
int cmp = x.left.info.compareTo(x.right.info);
if(cmp >= 0){
swapNode = x.left;
} else{
swapNode = x.right;
}
int cmpParChild = x.info.compareTo(swapNode.info);
if(cmpParChild < 0) {
swapNodeData(swapNode, x);
sink(swapNode);
}
}
}
String printThisLevel (Node rootnode, int level) {
StringBuilder s = new StringBuilder();
// Base case 1: if the current rootnode is null, return the current string.
if (rootnode == null) {
return s.toString();
}
// Base case 2: If you're at the first level, append the
// info field of the current rootnode.
if (level == 1) {
s.append( rootnode.info.toString());
}
// Recursive calls: otherwise call the method on the left
// and on the right of the next lower level.
else if (level > 1) {
s.append( printThisLevel(rootnode.left, level-1));
s.append( printThisLevel(rootnode.right, level-1));
}
return s.toString();
}
private int size(Node x){
if(x == null) return 0;
return x.N;
}
private Node insert(Node x, T data){
if(x == null){
lastInserted = new Node(data, 1);
return lastInserted;
}
// compare left and right sizes see where to go
int leftSize = size(x.left);
int rightSize = size(x.right);
if(leftSize <= rightSize){
// go to left
Node inserted = insert(x.left, data);
x.left = inserted;
inserted.parent = x;
} else{
// go to right
Node inserted = insert(x.right, data);
x.right = inserted;
inserted.parent = x;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
private Node resetLastInserted(Node x){
if(x == null) return null;
if(x.left == null && x.right == null) return x;
if(size(x.right) < size(x.left))return resetLastInserted(x.left);
else return resetLastInserted(x.right);
}
public void insert(T data){
root = insert(root, data);
swim(lastInserted);
}
public T getMax(){
if(root == null) return null;
return root.info;
}
public T removeMax(){
if(size() == 1){
T ret = root.info;
root = null;
return ret;
}
swapNodeData(root, lastInserted);
Node lastInsParent = lastInserted.parent;
T lastInsData = lastInserted.info;
if(lastInserted == lastInsParent.left){
lastInsParent.left = null;
} else{
lastInsParent.right = null;
}
Node traverser = lastInserted;
while(traverser != null){
traverser.N--;
traverser = traverser.parent;
}
lastInserted = resetLastInserted(root);
sink(root);
return lastInsData;
}
public int size(){
return size(root);
}
public boolean isEmpty(){
return size() == 0;
}
public String toString() {
// Create a StringBuilder object to make it more efficient.
StringBuilder sb=new StringBuilder();
// get the height of the tree
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
// for each level in the tree, call printThisLevel and
// append the output to the StringBuilder
for (int i=1; i<=height; i++) {
sb.append("level " + i + ": "+ printThisLevel(this.root, i) + "\n");
}
// Return the string of the StringBuilder object
return sb.toString();
}
public static void main (String[] args) {
LinkedMaxPQ<String> t = new LinkedMaxPQ<String>();
t.insert("a");
System.out.println(t.toString());
t.insert("b");
t.insert("c");
t.insert("d");
t.insert("e");
t.insert("f");
t.insert("g");
t.insert("h");
t.insert("i");
t.insert("j");
t.insert("k");
t.size();
t.removeMax();
t.getMax();
t.removeMax();
t.insert("x");
t.insert("y");
t.removeMax();
t.getMax();
System.out.println(t.toString());
}
}
In this line:
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
size should be size().
int height = (int)Math.ceil(Math.log(size()+1) / Math.log(2));
After this correction, the results are coming out.
However, there is a logic problem, which needs a solution.
For test case, testdata = new int[] {3, 5, 2, -7, 9, 4, 7};
The result is 9 4 7 -7 3 2 5
But correct result should be 9 5 7 -7 3 2 4 (from another array implementation).
I know the mistake comes from when at the 3rd levle, insert data {9}, its parent should be the 2nd leverl data {3} on the left, not the {2} on the right. Any thought to solve it?
I have been working on this problem for several hours now and I just cannot figure out what I am doing wrong here. Could anyone help point me in the right direction?
I was asked to write an Autocomplete program and I've completed everything except for this one method I cannot get working. Each term has: 1. String query and 2. long weight.
Here is the method:
public static Comparator<Term> byReverseWeightOrder() {
return new Comparator<Term>() { // LINE CAUSING PROBLEM
public int compare(Term t1, Term t2) {
if (t1.weight > t2.weight) { // LINE CAUSING PROBLEM
return -1;
} else if (t1.weight == t2.weight) {
return 0;
} else {
return 1;
}
}
};
}
My problem is that no matter how I mess with the method I always result in a NullPointerException(). Which, it points to this method (byReverseWeightOrder) as well as these two statements.
Arrays.sort(matches, Term.byReverseWeightOrder());
Term[] results = autocomplete.allMatches(prefix);
Here is the rest of the code if it can be found helpful:
Term
import java.util.Comparator;
public class Term implements Comparable<Term> {
public String query;
public long weight;
public Term(String query, long weight) {
if (query == null) {
throw new java.lang.NullPointerException("Query cannot be null");
}
if (weight < 0) {
throw new java.lang.IllegalArgumentException("Weight cannot be negative");
}
this.query = query;
this.weight = weight;
}
public static Comparator<Term> byReverseWeightOrder() {
return new Comparator<Term>() {
public int compare(Term t1, Term t2) {
if (t1.weight > t2.weight) {
return -1;
} else if (t1.weight == t2.weight) {
return 0;
} else {
return 1;
}
}
};
}
public static Comparator<Term> byPrefixOrder(int r) {
if (r < 0) {
throw new java.lang.IllegalArgumentException("Cannot order with negative number of characters");
}
final int ref = r;
return
new Comparator<Term>() {
public int compare(Term t1, Term t2) {
String q1 = t1.query;
String q2 = t2.query;
int min;
if (q1.length() < q2.length()) {
min = q1.length();
}
else {
min = q2.length();
}
if (min >= ref) {
return q1.substring(0, ref).compareTo(q2.substring(0, ref));
}
else if (q1.substring(0, min).compareTo(q2.substring(0, min)) == 0) {
if (q1.length() == min) {
return -1;
}
else {
return 1;
}
}
else {
return q1.substring(0, min).compareTo(q2.substring(0, min));
}
}
};
}
public int compareTo(Term that) {
String q1 = this.query;
String q2 = that.query;
return q1.compareTo(q2);
}
public long getWeight() {
return this.weight;
}
public String toString() {
return this.weight + "\t" + this.query;
}
}
BinarySearchDeluxe
import java.lang.*;
import java.util.*;
import java.util.Comparator;
public class BinarySearchDeluxe {
public static <Key> int firstIndexOf(Key[] a, Key key, Comparator<Key> comparator) {
if (a == null || key == null || comparator == null) {
throw new java.lang.NullPointerException();
}
if (a.length == 0) {
return -1;
}
int left = 0;
int right = a.length - 1;
while (left + 1 < right) {
int middle = left + (right - left)/2;
if (comparator.compare(key, a[middle]) <= 0) {
right = middle;
} else {
left = middle;
}
}
if (comparator.compare(key, a[left]) == 0) {
return left;
}
if (comparator.compare(key, a[right]) == 0) {
return right;
}
return -1;
}
public static <Key> int lastIndexOf(Key[] a, Key key, Comparator<Key> comparator) {
if (a == null || key == null || comparator == null) {
throw new java.lang.NullPointerException();
}
if (a == null || a.length == 0) {
return -1;
}
int left = 0;
int right = a.length - 1;
while (left + 1 < right) {
int middle = left + (right - left)/2;
if (comparator.compare(key, a[middle]) < 0) {
right = middle;
} else {
left = middle;
}
}
if (comparator.compare(key, a[right]) == 0) {
return right;
}
if (comparator.compare(key, a[left]) == 0) {
return left;
}
return -1;
}
}
AutoComplete
import java.util.Arrays;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
public class Autocomplete {
public Term[] terms;
public Autocomplete(Term[] terms) {
if (terms == null) {
throw new java.lang.NullPointerException();
}
this.terms = terms.clone();
Arrays.sort(this.terms);
}
public Term[] allMatches(String prefix) {
if (prefix == null) {
throw new java.lang.NullPointerException();
}
Term theTerm = new Term(prefix, 0);
int start = BinarySearchDeluxe.firstIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int end = BinarySearchDeluxe.lastIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int count = start;
System.out.println("Start: " + start + " End: " + end);
if (start == -1 || end == -1) {
// System.out.println("PREFIX: " + prefix);
throw new java.lang.NullPointerException();
} // Needed?
Term[] matches = new Term[end - start + 1];
//matches = Arrays.copyOfRange(terms, start, end);
for (int i = 0; i < end - start; i++) {
matches[i] = this.terms[count];
count++;
}
Arrays.sort(matches, Term.byReverseWeightOrder());
System.out.println("Finished allmatches");
return matches;
}
public int numberOfMatches(String prefix) {
if (prefix == null) {
throw new java.lang.NullPointerException();
}
Term theTerm = new Term(prefix, 0);
int start = BinarySearchDeluxe.firstIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int end = BinarySearchDeluxe.lastIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
System.out.println("Finished numberMatches");
return end - start + 1; // +1 needed?
}
public static void main(String[] args) throws IOException {
// Read the terms from the file
Scanner in = new Scanner(new File("wiktionary.txt"));
int N = in.nextInt(); // Number of terms in file
Term[] terms = new Term[N];
for (int i = 0; i < N; i++) {
long weight = in.nextLong(); // read the next weight
String query = in.nextLine(); // read the next query
terms[i] = new Term(query.replaceFirst("\t",""), weight); // construct the term
}
Scanner ip = new Scanner(System.in);
// TO DO: Data Validation Here
int k;
do {
System.out.println("Enter how many matching terms do you want to see:");
k = ip.nextInt();
} while (k < 1 || k > N);
Autocomplete autocomplete = new Autocomplete(terms);
// TO DO: Keep asking the user to enter the prefix and show results till user quits
boolean cont = true;
do {
// Read in queries from standard input and print out the top k matching terms
System.out.println("Enter the term you are searching for. Enter * to exit");
String prefix = ip.next();
if (prefix.equals("*")) {
cont = false;
break;
}
Term[] results = autocomplete.allMatches(prefix);
System.out.println(results.length);
for(int i = 0; i < Math.min(k,results.length); i++)
System.out.println(results[i].toString());
} while(cont);
System.out.println("Done!");
}
}
I apologize for the sloppy code, I have been pulling my hair out for awhile now and keep forgetting to clean it up.
Two examples:
Example 1:
int k = 2;
String prefix = "auto";
Enter how many matching terms do you want to see:
2
Enter the term you are searching for. Enter * to exit
auto
619695 automobile
424997 automatic
Example 2:
int k = 5;
String prefix = "the";
Enter how many matching terms do you want to see:
5
Enter the term you are searching for. Enter * to exit
the
5627187200 the
334039800 they
282026500 their
250991700 them
196120000 there
I have run into a problem converting pseudocode of Dijkstras algorithm into actual code. I was given and adjacency list such as "Location - adjacent location - distance to location," example for one node: AAA AAC 180 AAD 242 AAH 40.
My task was to read a file organized as adjacency list as described, and compute the shortest path from one node to another.
Here is the Dijkstra pseudocode:
void dijkstra( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v
if( !w.known )
{
DistType cvw = cost of edge from v to w;
if( v.dist + cvw < w.dist )
{
// Update w
decrease( w.dist to v.dist + cvw );
w.path = v;
}
}
}
}
im having the most trouble with the line "for each Vertex w adjacent to v"
Here is my nonworking code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class Dijkstra {
public static boolean isInteger(String s) {
return isInteger(s, 10);
}
public static boolean isInteger(String s, int radix) {
if (s.isEmpty())
return false;
for (int i = 0; i < s.length(); i++) {
if (i == 0 && s.charAt(i) == '-') {
if (s.length() == 1)
return false;
else
continue;
}
if (Character.digit(s.charAt(i), radix) < 0)
return false;
}
return true;
}
public static void dijkstra(Vertex[] a, Vertex s, int lineCount) {
int i = 0;
while (i < (lineCount)) // each Vertex v
{
a[i].dist = Integer.MAX_VALUE;
a[i].known = false;
i++;
}
s.dist = 0;
int min = Integer.MAX_VALUE; //
while (!(a[0].known == true && a[1].known == true && a[2].known == true && a[3].known == true
&& a[4].known == true && a[5].known == true && a[6].known == true && a[7].known == true
&& a[8].known == true && a[9].known == true && a[10].known == true && a[11].known == true
&& a[12].known == true)) {
System.out.println("here");
for (int b = 0; b < lineCount; b++) {
if (a[b].dist < min && a[b].known == false) {
min = a[b].dist;
}
}
int c = 0;
while (c < lineCount) {
if (a[c].dist == min && a[c].known == false) {
break;
}
c++;
}
System.out.println(min);
a[c].known = true;
int adjSize = a[c].adj.size();
int current = 0;
System.out.println(adjSize);
while (current < adjSize - 1) {
String currentAdjacent = (String) a[c].adj.get(current);
int p = 0;
while (p < lineCount) {
if (a[p].name.equals(currentAdjacent)) {
if (!a[p].known) {
String cvwString = (String) a[c].distance.get(current);
int cvw = Integer.parseInt(cvwString);
System.out.println(" This is cvw" + cvw);
System.out.println("Here2");
if (a[c].dist + cvw < a[p].dist) {
a[p].dist = a[c].dist + cvw;
a[p].path = a[c];
}
}
}
p++;
}
current++;
}
}
}
public static class Vertex {
public List adj; // Adjacency list
public List distance;
public boolean known;
public int dist; // DistType is probably int
public Vertex path;
public String name;
// Other fields and methods as needed
}
public static void printPath(Vertex v) {
if (v.path != null) {
printPath(v.path);
System.out.print(" to ");
}
System.out.print(v);
}
public static void main(String[] args) throws IOException {
int lineCounter = 0;
BufferedReader br = new BufferedReader(new FileReader("airport.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
lineCounter = lineCounter + 1;
}
Vertex[] arr = new Vertex[lineCounter];
for (int i = 0; i < lineCounter; i++) {
arr[i] = new Vertex();
arr[i].adj = new LinkedList<String>();
arr[i].distance = new LinkedList<Integer>();
}
;
//
int arrayCounter = 0;
String everything = sb.toString();
String[] lines = everything.split("\\s*\\r?\\n\\s*");
for (String line1 : lines) {
arr[arrayCounter] = new Vertex();
arr[arrayCounter].adj = new LinkedList<String>();
arr[arrayCounter].distance = new LinkedList<Integer>();
String[] result = line1.split("\\s+");
for (int x = 0; x < result.length; x++) {
if (x == 0) {
arr[arrayCounter].name = result[0];
continue;
} else if (isInteger(result[x])) {
arr[arrayCounter].distance.add(result[x]);
continue;
} else {
arr[arrayCounter].adj.add(result[x]);
continue;
}
}
arrayCounter++;
}
for (int i = 0; i < 12; i++) {
System.out.println(arr[i].name);
}
System.out.println(lineCounter);
dijkstra(arr, arr[3], lineCounter - 1);
printPath(arr[11]);
} finally {
br.close();
}
}
}
Using my vertex class as is I was using a series of while loops to first, traverse the adjacency strings stored in a linked list while comparing to see which vertex is equivalent to the adjacency list string. Is there a better way to code "for each Vertex w adjacent to v" using my Vertex class? And apologies ahead for messy code and any others style sins i may have committed. Thanks!
To solve this problem you need a bunch of "Node" objects, stored in a HashMap, keyed on Source Location.
In the node, you need a collection of references to adjacent "Node" objects (or at least their "key" so you can write logic against it. The "Node" also needs to know it's location and distance to each "adjacent" node. Think Lundon Underground Tube Maps - each station connects to at least one other station. Usually two or more. Therefore, adjacent nodes to tube stations are the immediate next stops you can get to from that station.
Once you have that data structure in place, you can then use a recursive routine to iterate through each individual node. It should then iterate through each child node (aka adjacent node), and track distances from the initial (source) node to the current node by storing this data in a HashMap and using the current accumulated distance whilst recursing (or "walking" the graph"). This tracking information should be part of your method signature when recursing. You will also need to track the current path you have taken when recursing, in order to avoid circular loops (which will ultimately and ironically cause a StackOverflowError). You can do this by using a HashSet. This Set should track the source and current node's location as the entry key. If you see this present during your recursion, then you have already seen it, so don't continue processing.
I'm not going to code the solution for you because I suspect that you ask more specific questions as you work your way through understanding the answer, which are very likely answered elsewhere.
I already build a binary search tree. The primitive data type I store in the tree is integer. I try to store it on a 2-D char array and then print it out as the graph shown below(the numbers represent row numbers and column numbers and I do not need to print it, ignoring "-" symbol please, I only use it to indicate the exact position)
-----0---1---2---3---4---5---6---7---8---9---10---11---12---13---14---15---16
0---------------------------------------12
1--------------------------------/-------------------\
2----------------------8--------------------------------------14
3-----------------/----------\ -----------------------------------------\
4-------------5----------------9-------------------------------------------34
5--------/-------------------------------------------------------------/-------------\
6---2---------------------------------------------------------24------------------------35
number 12 need to store on location [0][8], the middle of the first row.
number 4 store on[2][4], number 14=[2][12], 5=[4][2], 9=[4][9] and so on.
row number 1 which is second row, "/" is on position[1][6] and "\" is on position[1][10] etc.they are also on the middle between two numbers
following is my code
public class MainClass {
public static void main(String[] args) {
//level represents row number;
// start indicates the column I am going to
//store number in, and end is a fixed column number
// BinarySearchTree is a BinaryTree type instance,
// I already story integers on it and follow with the format
// of binary search trees, and I did tested it.
int level=0; int start=0; int end=80;
BinaryTree.plot(BinarySearchTree, level, start, end);
}
private static class BinaryTree {
private BinaryNode root;
static char[][] offset = new char [10][20];
public BinaryTree(){
root = null;
}
public BinaryTree(Object x){
root = new BinaryNode(x);
}
public boolean isEmpty(){
return root == null;
}
public Object getRootobj() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else
return root.element;
}
public BinaryTree getLeft() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.left;
return t;
}
}
public BinaryTree getRight() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.right;
return t;
}
}
public static void plot(BinaryTree t, int level, int start, int end){
if(!t.isEmpty()){
plot(t.getLeft(), level+2, start/2, end/2);
String string = Integer.toString((Integer)t.getRootobj());
for(char c: string.toCharArray())
offset[level][start++]=c;
if(!(t.getLeft().isEmpty()))
offset[++level][start/4*3] = '/';
if(!(t.getRight().isEmpty()))
offset[++level][((start+end)/2+start)/2] = '\\';
plot(t.getRight(), level+2, end/2, end);
}
for(int i = 0; i<10; i++){
for(int j= 0; j<20; j++)
System.out.print(offset[i][j]);
}
}
}
private static class BinaryNode {
Object element;
BinaryNode left,right;
BinaryNode() {
this(0);
}
BinaryNode(Object e) {
this(e, null, null);
}
BinaryNode(Object e, BinaryNode ln, BinaryNode m){
element=e;
left=ln;
right=m;
}
}
}
Question: the method plot I used to store and print out binarysearchtree did not work, which causes a java.lang.ArrayIndexOutOfBoundsException:
can anyone take a look at it. appreciated for the help.
Your fixed-size char-Array cannot cope with your dynamic sized BinaryTree. For your given example alone you need way more then 20 characters per line! That's where your Exception is coming from.
But to give you an idea of an alternative approach - even though it took a while, made the following additions to your code:
First, I added a method to the BinaryNode class:
int getDepth() {
int subTreeDepth;
if (left == null && right == null) {
subTreeDepth = 0;
} else if (left == null) {
subTreeDepth = right.getDepth();
} else if (right == null) {
subTreeDepth = left.getDepth();
} else {
subTreeDepth = Math.max(left.getDepth(), right.getDepth());
}
return 1 + subTreeDepth;
}
Second, I removed your fixed char-Array and replaced the whole plotting algorithm in your BinaryTree (I just couldn't wrap my head around all those relative array-index manipulations):
public void plot() {
if (root == null) {
throw new BinaryTreeException("Empty Tree");
}
int lineCount = 2 * root.getDepth() - 1;
StringBuilder[] lines = new StringBuilder[lineCount];
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
lines[lineIndex] = new StringBuilder();
}
// get the right most node (which contains the largest element value)
BinaryNode rightMostNode = root;
while (rightMostNode.right != null) {
rightMostNode = rightMostNode.right;
}
// check how many characters we have to reserve for a single node element
int maxElementLength = String.valueOf(rightMostNode.element).length();
plot(root, 0, 0, maxElementLength, lines);
for (StringBuilder singleLine : lines) {
System.out.println(singleLine.toString());
}
}
private void plot(BinaryNode subTreeRoot, int offset, int lineIndex, int elementLength, StringBuilder[] lines) {
int actualOffset;
if (subTreeRoot.left == null) {
actualOffset = offset;
} else {
actualOffset = offset + (int) Math.pow(2, subTreeRoot.left.getDepth() - 1) * elementLength;
}
StringBuilder currentLine = lines[lineIndex];
String elementValue = String.valueOf(subTreeRoot.element);
for (int lineFillIndex = currentLine.length() + elementValue.length() / 2; lineFillIndex < actualOffset; lineFillIndex++) {
currentLine.append(' ');
}
currentLine.append(elementValue);
if (subTreeRoot.left != null) {
// draw connection to left sub tree
int connectPosition = (actualOffset - offset) * 3 / 4 + offset;
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('/');
// insert the left part of the next value line
plot(subTreeRoot.left, offset, lineIndex + 2, elementLength, lines);
}
if (subTreeRoot.right != null) {
// draw connection to right sub tree
int connectPosition = actualOffset + elementLength - elementValue.length() / 2;
if (subTreeRoot.right.left != null) {
connectPosition += (int) Math.pow(2, subTreeRoot.right.left.getDepth() - 1) * elementLength / 2;
}
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('\\');
// insert the right part of the next value line
plot(subTreeRoot.right, actualOffset + elementLength, lineIndex + 2, elementLength, lines);
}
}
For a tree similar to the one, you included in your question:
BinaryTree binarySearchTree = new BinaryTree(
new BinaryNode(12,
new BinaryNode(8,
new BinaryNode(5,
new BinaryNode(3),
null),
new BinaryNode(9)),
new BinaryNode(14,
null,
new BinaryNode(34,
new BinaryNode(24),
new BinaryNode(35)))));
binarySearchTree.plot();
I get the following output:
12
/ \
8 14
/ \ \
5 9 34
/ / \
3 24 35
I am trying to complete an assignment where I need to write a Java program to take a string from the command line, and implement it as a Binary Tree in a specific order, then get the depth of the binary tree.
For example: "((3(4))7((5)9))"
would be entered as a tree with 7 as the root, 3 and 9 as the children, and 4 as a right child of 3, and 5 as a left child of 9.
My code is below.. The problem I am having is that, because I am basing my checks off of finding a right bracket, I am unsure how to get the elements correctly when they are not directly preceding the brackets, such as the 3 in the above string. Any direction would be greatly appreciated..
class Node {
int value;
Node left, right;
}
class BST {
public Node root;
// Add Node to Tree
public void add(int n) {
if (root == null) {
root = new Node( );
root.value = n;
}
else {
Node marker = root;
while (true) {
if (n < marker.value) {
if (marker.left == null) {
marker.left = new Node( );
marker.left.value = n;
break;
} else {
marker = marker.left;
}
} else {
if (marker.right == null) {
marker.right = new Node( );
marker.right.value = n;
break;
} else {
marker = marker.right;
}
}
}
}
} // End ADD
//Find Height of Tree
public int height(Node t) {
if (t.left == null && t.right == null) return 0;
if (t.left == null) return 1 + height(t.right);
if (t.right == null) return 1 + height(t.left);
return 1 + Math.max(height(t.left), height(t.right));
} // End HEIGHT
// Check if string contains an integer
public static boolean isInt(String s) {
try {
Integer.parseInt(s);
}
catch(NumberFormatException e) {
return false;
}
return true;
} // End ISINT
public int elementCount(String[] a) {
int count = 0;
for (int i = 0; i < a.length; i++) {
if (isInt(a[i])) count++;
}
return count;
}
} // End BST Class
public class Depth {
public static void main(String[] args) {
String[] a = args[0].split(" ");
BST tree = new BST();
int[] bcount = new int[10];
int[] elements = new int[10];
int x = 0, bracketcount = 0;
// Display entered string
System.out.print("Entered Format: ");
for (int j=0; j < a.length; j++) {
System.out.print(a[j]);
}
for (int i=0; i < a.length; i++) {
char c = a[i].charAt(0);
switch (c)
{
case '(':
bracketcount++;
break;
case ')':
if (isInt(a[i-1])) {
bcount[x] = bracketcount--;
elements[x++] = Integer.parseInt(a[i-1]);
}
break;
case '1':
case '7':
default : // Illegal character
if ( (a[i-1].charAt(0) == ')') && (a[i+1].charAt(0) == '(') ) {
bcount[x] = bracketcount;
elements[x++] = Integer.parseInt(a[i]);
}
break;
}
}
System.out.println("\nTotal elements: " + tree.elementCount(a));
// Display BracketCounts
for (int w = 0; w < x; w++) {
System.out.print(bcount[w] + " ");
}
System.out.println(" ");
// Display Elements Array
for (int w = 0; w < x; w++) {
System.out.print(elements[w] + " ");
}
System.out.println("\nDepth: " + tree.height(tree.root));
// Build the tree
for (int y = 0; y < x-1; y++) {
for (int z = 1; z < tree.height(tree.root); z++) {
if (bcount[y] == z) {
tree.add(elements[y]);
}
}
}
} // End Main Function
public static boolean isInt(String s) {
try {
Integer.parseInt(s);
}
catch(NumberFormatException e) {
return false;
}
return true;
}
} // End Depth Class
I would do a couple of statements to get access to a tree with that kind of shape:
For input string : input= "((3(4))7((5)9))"
You could do :
public class Trial {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String input = "((3(4))7((5)9))";
String easier = input.replaceAll("\\(\\(", "");
String evenEasier = easier.replaceAll("\\)\\)", "");
System.out.println(evenEasier);
int firstVal = Integer.parseInt(evenEasier.substring(0, 1));
int firstBracketVal = Integer.parseInt(evenEasier.substring(2, 3));
int middleVal = Integer.parseInt(evenEasier.substring(3, 4));
int secondBracketVal = Integer.parseInt(evenEasier.substring(4,5));
int lastVal = Integer.parseInt(evenEasier.substring(6));
System.out.println("First Val:"+firstVal);
System.out.println("First bracket Val:"+firstBracketVal);
System.out.println("Middle Val:"+middleVal);
System.out.println("Second Bracket Val:"+secondBracketVal);
System.out.println("Last Val:"+lastVal);
}
}
This however would only ever work for entries in that specific format, if that were to change, or the length of the input goes up - this would work a bit or break.....If you need to be able to handle more complicated trees as input in this format a bit more thought would be needed on how to best handle and convert into your internal format for processing.
pseudocode:
function getNode(Node)
get one char;
if (the char is "(")
getNode(Node.left);
get one char;
end if;
Node.value = Integer(the char);
get one char;
if (the char is "(")
getNode(Node.right);
get one char;
end if;
//Now the char is ")" and useless.
end function
Before calling this function, you should get a "(" first.
In this method, the framwork of a Node in string is "[leftchild or NULL] value [rightchild or NULL])".
"("is not belong to the Node, but ")" is.