Java - Iterative deepening search with nodes - java

I'm in the process of designing a program that is meant to search through a two-dimensional array of numbers that represents a map for a path to a specified end point. I've been using nodes that have several parameters, most prominently adjacent north, south, east, and west nodes each representing a square within the map. The search method I'm currently trying to finish is with iterative deepening but every time I try running the program, I wind up with a stack overflow error. This is the iterative deepening class.
import java.util.*;
import java.io.*;
public class IDeepeningSearch {
private Node start;
private Node end;
private int[][] map;
private ArrayList<Node> solution;
//Build using file handler
public IDeepeningSearch(String file){
FileHandler handle = new FileHandler(file);
//Create map
map = handle.getMap();
//Start node coordinates and value
start = new Node();
start.setRow(handle.getSRow());
start.setCol(handle.getSCol());
start.setValue(map[start.getRow()][start.getCol()]);
//End node coordinates
end = new Node();
end.setRow(handle.getERow());
end.setCol(handle.getECol());
end.setValue(map[start.getRow()][start.getCol()]);
}
//Runs search
public void run(){
int i = 0;
solution = new ArrayList<Node>();
//Value of i indicates depth to be explored; will increment with each failure
while(solution.isEmpty()){
search(start, i);
i++;
}
if(!solution.isEmpty()){
System.out.println("It worked.");
}
System.out.println("If you're not seeing the other message then it failed.");
}
//Building tree
public void build(Node head){
setNLeaf(head);
setSLeaf(head);
setELeaf(head);
setWLeaf(head);
// if(head.getNorth() != null){
// build(head.getNorth());
// }
// if(head.getSouth() != null){
// build(head.getSouth());
// }
// if(head.getEast() != null){
// build(head.getEast());
// }
// if(head.getWest() != null){
// build(head.getWest());
// }
}
//Performs search
public void search(Node head, int depth){
if(head.getRow() == end.getRow() && head.getCol() == end.getCol()){
solution.add(head);
return;
}
else{
if(depth == 0){
return;
}
build(head);
if(head.getNorth() != null){
search(head.getNorth(), depth--);
}
if(head.getSouth() != null){
search(head.getSouth(), depth--);
}
if(head.getEast() != null){
search(head.getEast(), depth--);
}
if(head.getWest() != null){
search(head.getWest(), depth--);
}
}
}
//Sets north leaf
public void setNLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != 0 && map[node.getRow() - 1][node.getCol()] != 0){
Node n = new Node();
n.setRow(node.getRow() - 1);
n.setCol(node.getCol());
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setNorth(n);
}
}
//Sets south leaf
public void setSLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != (map.length - 1) && map[node.getRow() + 1][node.getCol()] != 0){
Node n = new Node();
n.setRow(node.getRow() + 1);
n.setCol(node.getCol());
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setSouth(n);
}
}
//Sets east leaf
public void setELeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != (map[0].length - 1) && map[node.getRow()][node.getCol() + 1] != 0){
Node n = new Node();
n.setRow(node.getRow());
n.setCol(node.getCol() + 1);
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setEast(n);
}
}
//Sets west leaf
public void setWLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getCol() != 0 && map[node.getRow()][node.getCol() - 1] != 0){
Node n = new Node();
n.setRow(node.getRow());
n.setCol(node.getCol() - 1);
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setWest(n);
}
}
}
I thought I was doing this correctly but the errors I've been getting have been pretty constant. This is what I wind up with.
Exception in thread "main" java.lang.StackOverflowError
at Node.setSouth(Node.java:88)
at IDeepeningSearch.setSLeaf(IDeepeningSearch.java:113)
at IDeepeningSearch.build(IDeepeningSearch.java:48)
at IDeepeningSearch.search(IDeepeningSearch.java:75)
at IDeepeningSearch.search(IDeepeningSearch.java:77)
at IDeepeningSearch.search(IDeepeningSearch.java:80)
at IDeepeningSearch.search(IDeepeningSearch.java:77)
The second-to-last and last lines repeat. I've tried building a full tree as well but that either gives me another stack overflow error or a null pointer exception. I'm not really sure what the issue is here but if I can fix this, I'm sure I can finish my breadth-first search method as well.

depth-- evaluates to the original value of depth. This means that the unmodified version of depth is being passed to the recursive call to search(), so your code is never approaching the base case. Try depth-1 instead. Or, if you need the value of the local variable depth to change, --depth.
For example, this will continually print 10 until it reaches stack overflow
public void foo(int x) {
if (x == 0) {
return;
}
System.out.println(x);
foo(x--);
}
foo(10);

The StackOverflowError is because of the flawed recursive calls of search(node, depth--) as Chris Rise has mentioned in his answer. Try --depth to fix this.
There is also poor memory management in this code, which is wasting heap memory that could either slow the program due to several calls to GC (Garbage-Collector) or lead to an OutOfMemeoryError! This problem is visible in the setXLeaf(Node n) methods (e.g. setNLeaf(Node north) etc.) where every time you are creating a new Node, while this can be done only when it's necessary with a simple check:
if (node.getSouth() == null) {
Node n = new Node();
n.setParent(node);
node.setSouth(n);
}
node.getSouth().setRow(node.getRow() + 1);
node.getSouth().setCol(node.getCol());
node.getSouth().setValue(map[node.getRow() + 1][node.getCol()]);
This way you will avoid creating new objects that are unnecessary. This should be fixed in all the setXLeaf(...) methods.

Related

Iterative Post order traversal without visited array

I have recently started learning computer science and Java coding and came across Traversal techniques. I am writing a Java code using Stack. I have been with this issue and couldn't find any solution. Is there anyway we can implement Post Order traversal using only one stack (without any extra data structure or extra space) ?
I have tried doing it and here is my code.
class node {
int data;
node left, right;
node(int val){
data = val;
left = right = null;
}
}
public class binaryt {
public static void postorder(node root) {
node current = root;
Stack<node> st = new Stack<>();
System.out.println();
System.out.print("Post-order : ");
while(current!=null) {
st.push(current);
current = current.left;
}
while(!st.empty()) {
current = st.pop();
if(current.right==null) {
System.out.print(current.data+" ");
current = null;
}
else {
st.push(current);
current = current.right;
while(current!=null) {
st.push(current);
current = current.left;
}
}
}
}
public static void main(String[] args) {
node root=null;
root = new node(12);
root.left = new node(8);
root.left.left = new node(2);
root.left.right = new node(9);
root.right= new node(16);
root.right.left= new node(13);
root.right.right= new node(18);
postorder(root);
}
}
I am unable to find what's wrong with the code as it is going in infinite loop. If anyone could help me, that would be huge favor.
Thank you so much.
The best way to learn these annoying algorithms is to suffer a bit and find your own solution that will stick in your brain - so you're doing the right thing. This one is always hard for me.
do
while(root != null)
push root.right to stack if not null
push root
root = root.left to stack
root = stack.pop()
if (root.right == stack.peek)
stack.pop()
push root to stack
root = root.right
else
print root
root = null;
while stack ! empty
Your Problem
So, there are probably a few general things wrong in the attempt you showed. But here's the one I'd fix first, then I think you'll be able to get the others:
You can't just go left down the whole tree to start with. You need to go left only after you check the right node and add it to the stack. Remember, a recursive implementation would already have the root/current frame existing, then it would call the left and right trees. So, that means the current frame goes last after the left and right calls finish. So, the function call stack logically holds the left sub-tree, then the right-sub-tree, then the current frame.
This is what is happening in your code :
first you are pushing 12,8 and 2 in the Stack
Then there is no left child for 2 , so you come to while
now 2 is popped out , and it has no right child, so now two values in stack 8,12
Next comes 8 it has a right child, you are pushing 8 into Stack again.
Now you are taking 9 as current and pushing it into Stack.
Now you are checking left of 9 which is null.
so you are again starting with while(!st.empty()) { loop which has elements 9, 8,12
again same thing repeats and your while loop never ends
you can also see on console : Post-order : 2 9 9 9 9 ..... Continues
So that is the issue.
Below is a solution :
public static void postorderIter( node root) {
if( root == null ) return;
Stack<node> s = new Stack<node>( );
node current = root;
while( true ) {
if( current != null ) {
if( current.right != null )
s.push( current.right );
s.push( current );
current = current.left;
continue;
}
if( s.isEmpty( ) )
return;
current = s.pop( );
if( current.right != null && ! s.isEmpty( ) && current.right == s.peek( ) ) {
s.pop( );
s.push( current );
current = current.right;
} else {
System.out.print( current.data + " " );
current = null;
}
}
}
Here's an example that relies on recursion to make it more readable.
public static void postorder(node root) {
Stack<node> nodes = new Stack<>();
node curr = root;
postOrderRecursive(curr, nodes);
int size = nodes.size();
while(size > 0){
System.out.println(nodes.elementAt(0).data);
nodes.remove(0);
size = nodes.size();
}
}
private static void postOrderRecursive(node n, Stack<node> nodes){
if(n.left != null)
postOrderRecursive(n.left, nodes);
if(n.right != null)
postOrderRecursive(n.right, nodes);
nodes.push(n);
}
Output given your initialization:
2
9
8
13
18
16
12

Recursively count the number of leaves in a binary tree without given parameters

I am struggling to figure out how to code a recursive algorithm to count the number of leaves in a Binary Tree (not a complete tree). I get as far as traversing to the far most left leaf and don't know what to return from there. I am trying to get the count by loading the leaves into a list and getting the size of that list. This is probably a bad way to go about the count.
public int countLeaves ( ) {
List< Node<E> > leafList = new ArrayList< Node<E> >();
//BinaryTree<Node<E>> treeList = new BinaryTree(root);
if(root.left != null)
{
root = root.left;
countLeaves();
}
if(root.right != null)
{
root = root.right;
countLeaves();
}
if(root.left == null && root.right == null)
{
leafList.add(root);
}
return();
}
Elaborating on #dasblinkenlight idea. You want to recursively call a countleaves on root node & pass back the # to caller. Something on the following lines.
public int countLeaves() {
return countLeaves(root);
}
/**
* Recursively count all nodes
*/
private static int countLeaves (Node<E> node) {
if(node==null)
return 0;
if(node.left ==null && node.right == null)
return 1;
else {
return countLeaves(node.left) + countLeaves(node.right);
}
}
Edit: It appears, a similar problem was previously asked counting number of leaf nodes in binary tree
The problem with your implementation is that it does not restore the value of member variable root back to the state that it had prior to entering the method. You could do it by storing the value in a local variable, i.e.
Node<E> oldRoot = root;
... // your method goes here
root = oldRoot;
However, a better approach is to take Node<E> as an argument, rather than relying on a shared variable:
public int countLeaves() {
return countLeaves(root);
}
private static int countLeaves (Node<E> node) {
... // Do counting here
}

Stack_Overflow_error while calling mergeSort method

I’ve been doing this problem:
I created one file which takes random numbers and I stored those numbers in a SinglyLinkedList data structure and I'd like to perform a mergeSort to sort these random numbers.
Everything works fine for smaller no of input.
But when I insert 10000 numbers, it starts giving ‘stack_overflow’ error at around 9800 no(at displaying numbers only) and when I insert 0.1 million numbers- it works well till 99700 numbers but then it starts showing errors for the rest of the numbers.
So what exactly the reason would be behind this error (I know it’s because it gets lost in recursive function)
Please help me out here, I'm not able to track the problem which causes this error.
Here's my main method code:
FileReader fr = new FileReader("C://my_folder//file_List.txt");
BufferedReader br = new BufferedReader(fr);
LinkedListNode lln = new LinkedListNode();
String str;
while((str=br.readLine())!=null){
/* This insertAtEnd appends the number to the SinglyLinkedList*/
lln.insertAtEnd(Integer.parseInt(str));
System.out.println(" "+str);
}
/*This method displays the elements of a LinkedList*/
Node res = lln.traverse();
System.out.println("\n");
mergeSortLinkedList ms = new mergeSortLinkedList();
ms.sort(res);
here's my sort method code:
public void sort(Node n){
Node tmp = n;
MergeSort(tmp);
}
Node a;
Node b;
public void MergeSort(Node headRef){
Node head1 = headRef;
if(head1 == null || head1.next == null){
return;
}
System.out.print("hi..");
Node Euler = splitList(head1);
printList(Euler);
}
/* perform merge sort on the linked list */
public Node splitList(Node head1){
Node slow;
Node fast;
Node left, right;
if(head1 == null || head1.next == null){
left = head1;
right = null;
return head1;
}
else{
slow = head1;
fast = head1.next;
while(fast!=null){
fast = fast.next;
if(fast!=null){
slow = slow.next;
fast = fast.next;
}
}
left = head1;
right = slow.next;
slow.next = null;
}
return SortedMerge(splitList(left),splitList(right));
}
/* merge the lists.. */
public Node SortedMerge(Node a, Node b){
Node result = null;
if(a == null){
return b;
}
else if( b == null){
return a;
}
if(a.data < b.data){
result = a;
result.next = SortedMerge(a.next, b);//getting error at this line
}
else{
result = b;
result.next = SortedMerge(a,b.next);//getting error at this line
}
return result;
}
public void printList(Node Euler){
System.out.println("\nPrinting sorted elements");
Node Ref = Euler;
int count = 0;
while(Ref!=null){
count++;
System.out.println(count+"-"+Ref.data);
Ref = Ref.next;
}
}
have you considered using Collections.sort() from the JDK, which will do a merge-sort? Java 8 has also a parallelSort which does a parallel merge-sort.
I’d like to give you a update.
By changing the stack size, I did able to run my program properly.
The reason it was causing
Exception in thread "main" java.lang.StackOverflowError is because it was getting out of stack size.
So I searched around and got this solution.
Go to the project properties- Inside run, go to the VM option and put this in argument -Xss100m to make it run!
Now it is able to sort more than 1 million numbers :D
Other suggestions / solutions are welcome.

Setting parents in tree

I have a huffman binary tree that starts with an empty node a.
A points to a left node and a right node, which also point to left and right nodes. Is it possible to set the parent nodes for each node recursively after having this tree?
This is the code I am thinking:
public Node setParents(Node n)
{
if(n.getZero() == null && n.getOne() == null)
{
return n;
}
Node a = setParents(n.getZero()); // Zero being left
a.setParent(n);
Node b = setParents(n.getOne()); // One being right.
b.setParent(n);
}
Here is how I am currently creating the tree by using a priority queue with values sorted least to greatest.
public Node createTree(PriorityQueue<Node> pq)
{
while(pq.size() > 1)
{
Node n = new Node();
Node a = pq.poll();
if(pq.size() > 0)
{
Node b = pq.poll();
n = new Node(a.getFrequency() + b.getFrequency());
n.setZero(a);
a.setWhich(0);
a.setParent(n);
n.setOne(b);
b.setWhich(1);
b.setParent(n);
}
else
{
n = new Node(a.getFrequency());
n.setZero(a);
a.setWhich(0);
n.setParent(n);
n.setOne(null);
}
pq.add(n);
}
Node n = pq.poll();
n.setParent(null);
setParents(n.getZero());
setParents(n.getOne());
return n;
}
I just need to make sure each node has a parent, which I don't know where to start from here.. Any help?
Some comments to your code that may help
1 . Do not use getters and setters in your study samples for simple assignments and reads, they are hard to understand.
2 . If you prepare some object do not mix this preparation with others
n.setZero(a);
a.setWhich(0);
a.setParent(n);
n.setOne(b);
3 . From what I understand there is a chance to get NPE
if(pq.size() > 0) {
Node b = pq.poll();
}
}
Node n = pq.poll();
n.setParent(null); <- n can be null
4 . Java has nice feature called Enums for this
a.setWhich(0);
b.setWhich(1);
Here is how to set parents starting from the root
public void fixParents(Node parentNode)
{
if (parentNode.zero != null) {
parentNode.zero.parent = parentNode;
fixParents(parentNode.zero);
}
if (parentNode.one != null) {
parentNode.one.parent = parentNode;
fixParents(parentNode.one);
}
}
UPD
One more thought. You set parents in your tree building function. So you should just check that parents are correct but not re-setting them.
public void checkParents(Node parentNode) throws Exception
{
if (parentNode.zero != null) {
if (parentNode.zero.parent != parentNode) {
throw new Exception( here include info about the parentNode.zero );
}
checkParents(parentNode.zero);
}
if (parentNode.one != null) {
if (parentNode.one.parent != parentNode) {
throw new Exception( here include info about the parentNode.one );
}
checkParents(parentNode.one);
}
}

How do I traverse a link list looking two nodes ahead?

I have a link list, and I want to be able to look two nodes ahead. I need to check if the first two nodes have integers, and if they do, and the third node says ADD, then I need to condense that information into one node and free the other two nodes.
I'm confused about what should go in my while loop. I check if the third node points to null, but somehow that's not giving me the right output. I don't know if I'm handling my node.next correctly either. Some of this is pseudocode now.
while(node1.next.next.next != NULL){
if((node1.data.isInteger() && (node2.data.isInteger()){
if(node3.data.equals('add')){
node1.data = node1.data + node2.data;
} else {
//ERROR
}
garbage_ptr1 = node2;
garbage_ptr2 = node3;
node1.next = node3.next;
free(garbage_ptr1);
free(garbage_ptr2);
node2.next = node1.next.next;
node3.next = node2.next.next;
} else {
node1.next = node1.next.next;
node2.next = node1.next.next;
node3.next = node2.next.next;
}
An approach that I find easier is to maintain a small array that acts as a window onto the list, and to look for matches on the array. The code also becomes a lot cleaner and simpler if you move your null checks into utility methods. By doing these things, the loop over the list only needs to check the last element of the window to terminate.
A sketch of this in Java:
/* small utility methods to avoid null checks everywhere */
public static Node getNext(Node n) { return n != null ? n.next : null; }
public static boolean isInteger(Node n) {
return (n != null) && (n.data != null) && (n.data instanceof Integer);
}
public static boolean isAdd(Node n) {
return (n != null) && (n.data != null) && n.data.equals("add");
}
/* checks for a match in the 3-node window */
public boolean isMatch(Node[] w) {
return isInteger(w[0]) && isInteger(w[1]) && isAdd(w[2]);
}
/* Loads the 3-node window with 'n' and the next two nodes on the list */
public void loadWindow(Node[] w, Node n) {
w[0] = n; w[1] = getNext(w[0]); w[2] = getNext(w[1]);
}
/* shifts the window down by one node */
public void shiftWindow(Node[] w) { loadWindow(w, w[1]); }
...
Node[] window = new Node[3];
loadWindow( window, node1 );
while (window[2] != null) {
if (isMatch(window)) {
window[0].data = stack[0].data + stack[1].data;
window[0].next = window[2].next;
loadWindow(window, window[0]); // reload the stack after eliminating two nodes
} else {
shiftWindow( window );
}
}

Categories