Binary Search tree, inorder method iterative not working - java

I am currently taking a data structure class in college and we are learning about binary search trees using linked lists. We have gone over the inOrder method recursively but I wanted to try to do the method iteratively. After some research I realized I have to use a stack as i traverse through the tree. I am able to get the the end of the left most side of the tree, however traversing back up the tree is where I am having trouble. I have tried various version of my code but I keep ending up with with a nil pointer exception or it prints out of order.
public void inOrder(){
// implement this method using non-recursive solution
if(m_root==null){
return;
}
Stack<BSTNode> myStack= new Stack<BSTNode>();
BSTNode current=m_root;
while (current!= null){
myStack.push(current);
current=current.getLeft();
}
while (current!=null&& !myStack.isEmpty()){
current=myStack.peek();
System.out.print(current.getInfo()+" ");
myStack.pop();
if(current.getRight()!=null){
myStack.push(current);
}
}
}

From what I can see there are a few problems with your code in the second while loop. The idea you have is in the right direction however there some logic errors. The conditions you have are correct but should not be together, they should be separated. the code below achieve what you are looking for.
public void inOrder(){
// implement this method using non-recursive solution
if(m_root==null){
return;
}
Stack<BSTNode> myStack= new Stack<BSTNode>();
BSTNode current=m_root;
while (current!= null){
myStack.push(current);
current=current.getLeft();
}
while (!myStack.isEmpty()){
current=(BSTNode)myStack.pop();
System.out.print(current.getInfo()+" ");
if(current.getRight() != null){
current=current.getRight();
while (current!= null){
myStack.push(current);
current=current.getLeft();
}
}
}
}

For starters, you have in your code two major flaws: you leave the first while loop with current pointing to null and thus you never enter the second while loop. Moreover, I think this
if(current.getRight()!=null){
myStack.push(current);
}
should be corrected with myStack.push(current.getRight());, otherwise you're trying to push over and over just the element you popped and you would enter an endless loop. But even so the logic of the exploration is wrong since you'll never go to the left of a node you arrived from a right link.
I tried to start from your code and create a working inorder traversal:
public void inOrder(){
Stack<BSTNode> myStack= new Stack<BSTNode>();
Set<BSTNode> visited = new HashSet<BSTNode>();
BSTNode current = m_root;
if(current!= null)
myStack.push(current);
while (!myStack.isEmpty()){
current = myStack.peek();
if(current.getLeft()!= null && !visited.contains(current.getLeft()))
myStack.push(current.getLeft());
else{
//here you explore the parent node
System.out.print(current.getInfo()+" ");
visited.add(current);
myStack.pop();
//and then you see if it has children on the right
if(current.getRight()!=null && !visited.contains(current.getRight))
myStack.push(current.getRight());
}
}
}

Related

Compilation error while implementing the Depth first search Recursively

I am new to using recursion for my methods. I tend to steer away from them for quite a few reasons. However, for a project, it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph.
Since I am not too well versed in recursion, I don't understand why I am getting the following error.
This method must return a result of type LinkedList.Node
The code I have currently is:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
DFSTime(node.nextNode);
}
}
It is unfinished code since I still need to implement some logic, however, I don't understand how to eliminate the error. Is there something very basic that I am missing?
The reason of the compilation error is pretty trivial. The compiler clearly tells that didn't provide the result to return for all possible cases.
The more important is that your current approach is not correct.
it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph
There are crucial things to consider:
Field nextNode is very suspicious. If each Node holds a reference pointing to a single node only, in fact the data structure you've created by definition isn't a Graph, but a Singly linked list. And doesn't make sense to implement DFS for a list. Every node should point to a collection of nodes, no to a single node.
You have to distinguish somehow between unvisited nodes and nodes that are already visited. Or else you might and up with infinite recursion. For that, you can define a boolean field isVisited inside the Node, or place every visited node into a HashSet.
Since you've chosen to create a recursive implementation of DFS, you don't need to create a stack. It's required only for iterative implementation.
Don't overuse global variables. I guess you might want to be able to check whether it is possible to reach different airports of destination without reinstantiating the graph.
Use getters and setters instead of accessing fields directly. It's a preferred practice in Java.
Your method might look like this (it's not necessary that element should be of type String it's just an illustration of the overall idea):
public Node DFSTime(Node node, String destinationAirport){
if(node == null || node.isVisited()) {
return null;
}
if (node.getElement().equals(destinationAirport)) {
System.out.println("The destination airport was found");
return node;
}
node.setVisited(true);
for (Node neighbour: node.getNeighbours()) {
Node result = DFSTime(neighbour, destinationAirport);
if (result != null) return result;
}
return null;
}
And the node might look like this:
public class Node {
private String element;
private List<Node> neighbours;
private boolean isVisited;
public Node(String element, List<Node> neighbours) {
this.element = element;
this.neighbours = neighbours;
}
public void setVisited(boolean visited) {
isVisited = visited;
}
public boolean isVisited() {
return isVisited;
}
public void addNeighbours(Node neighbour) {
neighbours.add(neighbour);
}
public String getElement() {
return element;
}
public List<Node> getNeighbours() {
return neighbours;
}
}
You should have a default return statement at the end of the function after the closing of the else.
In methods conditional blocks (if-else), you need to make sure you are returning appropriate Type from all conditional statements, so that there is no compile-time error. In your case, else block is recursively calling DFSTime(..) without returning anything.
You might want to return reference which gets called via recursive call, something like below:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
Node node = DFSTime(node.nextNode);
return node;
}
}

Java - Convert a Tree to a Lists of Nodes with same depth

I am trying to write a code to convert a binary tree to a lists of nodes with same depth. If a tree has depth d, then d lists will be created. The logic is to do in-order traversal and add the currently traversed node to the list of appropriate depth.
public void treeToListofNodesByLevel(Node<T> n,int depth, ArrayList<LinkedList<Node<T>>> treeList){
if(n.right != null){
inOrderWithHeight(n.right, depth + 1);
}
if(treeList.size() >= depth){
treeList.add(depth, new LinkedList<Node<T>>() );
}
treeList.get(depth).add(n);
if(n.left != null){
inOrderWithHeight(n.left, depth + 1);
}
}
and then calling:
ArrayList<LinkedList<Node<T>>> result = new ArrayList<LinkedList<Node<T>>>();
treeToListofNodesByLevel(root, 0, result);
Will this work ? Are there any corner cases I am not handling ?
Also, right now I am passing the List of List to be returned by the method because I can not think of a way to initialize it in the method and returning it at then end while also maintaining the recursive structure. Is there a better way to do this ?
You have the general concept pretty much perfect. It will work, and should handle all cases.
However, you have a few errors in the details:
Your check for when to add a new list has the comparison in the wrong direction. It should be if (treeList.size() <= depth).
Each call to inOrderWithHeight() (which you haven't provided any code of) should be a recursive call to treeToListofNodesByLevel(). Keep the first two arguments as they are, and just pass the treeList for the third.
This one's more a style issue, but parameter types should generally be declared as the highest level type that satisfies what you actually need. There is no need here to specify ArrayList or LinkedList, any List will do. Change the treeList parameter's type to List<List<Node<T>>>.
For the matter of initializing the List inside the method while also using recursion, that's the sort of thing that implementation helper methods are for. Take the current body of treeToListofNodesByLevel and move it into a private method (with the recursive calls changed so the private method calls itself), let's call it treeToListofNodesByLevelHelper. Then change the current public method to this:
public List<List<Node<T>>> treeToListofNodesByLevel(Node<T> node) {
List<List<Node<T>>> result = new ArrayList<>();
treeToListofNodesByLevelHelper(node, 0, result);
return result;
}
I cannot understand what the method "inOrderWithHeight" is doing. What I do for this question (not optimized) is to traverse like BFS using two queues and for each iteration adding the nodes of that depth to the list of that iteration (each iteration is traversing one depth of the tree). Here is my code to do that for a binary tree as you supposed in your answer:
Queue<Node<T>> queue1 = new LinkedList<Node<T>>() ;
Queue<Node<T>> queue2 = new LinkedList<Node<T>>() ;
public void treeToListofNodesByLevel(Node<T> root, ArrayList<LinkedList<Node<T>>> treeList) {
if (root == null)
return;
int curr_depth = 0;
queue1.add(root);
while(!queue1.isEmpty()){
treeList.add(curr_depth, new LinkedList<Node<T>>());
while(!queue1.isEmpty()){
Node<T> node = queue1.remove();
treeList.get(curr_depth).add(node);
if(node.left != null) queue2.add(node.left);
if(node.right != null) queue2.add(node.right);
}
curr_depth++;
while(!queue2.isEmpty()){
Node<T> node = queue2.remove();
queue1.add(node);
}
}
}
I wrote this on the fly without syntax checking and may have compiler errors. But hopefully you get the idea.
Why you just use the same function the code will be more beautifull :
public void treeToListofNodesByLevel(BinaryTree node, int currentDepth, List<List<BinaryTree>> result){
// Check if the list for the currentDepth is created
if(result.get(currentDepth) != null){
result.add(currentDepth, new ArrayList<BinaryTree>())
}
// Add the current node to the list
result.get(currentDepth).add(node);
// Recursive the left node
if(node.left != null){
treeToListofNodesByLevel(node.left, currentDepth+1, result);
}
// Recursive the right node
if(node.right != null){
treeToListofNodesByLevel(node.right, currentDepth+1, result);
}
}
In your main function :
List<List<BinaryTree>> result = new ArrayList<>();
BinaryTree root = new BinaryTree();
treeToListofNodesByLevel(root, 0, result);

Linked lists method not working properly (java)

I've written a class which represents a polynom using a linked list (members in that list are objects of another class I made called PolyNodes).
In that class I've written this method:
public Polynom addNode (PolyNode p)
{
if (p==null) //if the polynode to be added is null, the same polynom is returned
return this;
if (_head==null) //If the head is null, the polynom is empty and the polynode becomes the polynom
{
_head=p;
return this;
}
PolyNode curr = _head, prev = null;
while(curr != null) //when curr becomes null that means we reached the end of the polynom hence we reached the end of the loop as well
{
if (p.getPower() > curr.getPower()) //Upon reaching the first term whose power is lower than p's power
{
p.setNext(curr);
if (prev == null) //When curr is the polynom's head
_head = p;
else
prev.setNext(p);
return this;
}
else if (p.getPower() == curr.getPower()) //If the polynom already has a term with the same power, p's and curr's coefficients are summed up
{
curr.setCoefficient(curr.getCoefficient() + p.getCoefficient());
return this;
}
prev = curr;
curr = curr.getNext();
}
//If the method reached outside of the loop then there is no term in the polynom whose power is smaller than p's, and p will become the last term in the polynom
p.setNext(null);
prev.setNext(p);
return this;
}
The problem started when I tried writing an addPol() method.
public Polynom addPol (Polynom other)
{
for (PolyNode temp=other._head ; temp!=null ; temp=temp.getNext())
{
addNode(temp);
}
return this;
}
I can't figure out why, but I'm getting wrong results. I went through the code dozens of times and still couldn't find anything that could cause the problem.
problem goes as follows:
when I print list1 I get:
-5.0x^20+5.0x^17+4.0x^11+6.0x^8-5.0x^7+16.0x+1.0
when I print list2 I get
-3.0x^100+2.0x^17-3.0x^4+4.0x
however, when I print list1.addPol(list2)
-3.0x^100-10.0x^20+10.0x^17+8.0x^11+12.0x^8-10.0x^7+32.0x+2.0
If anyone could please tell me what is causing this I would greatly appriciate it. thanks in advance.
When you add the node to a new list its properties get changed, so then when you move onto next you move to the next in the second list.
You would be better off just using the provided LinkedList class for this rather than trying to re-invent it yourself.
Something like:
PolyNode copy = new PolyNode();
copy.setCoefficienttemp.getCoefficient());
copy.setPower(temp.getPower());
addNode(copy);
As mentioned, otherwise temp.getNext() will be changed in the original list.
It would be more abstract to have a class Term + next == PolyNode without next.

Anyone know why this method for linked list keeps on going forever?

I have this linked list method that is used to insert before, so it takes a node and puts it before the beforeNode. Currently it does that, but then it goes on forever and makes the linked list infinitely big when it should only be four long. Does anyone see why it keeps on going?
private void insertBefore(Node aNode, Node beforeNode)
{
if(this.getPrevious(beforeNode) != null) {
this.getPrevious(beforeNode).setNext(aNode);
// aNode.setPrevious(beforeNode);
//this.getPrevious(this.getPrevious(beforeNode)).setNext(aNode);
} else {
head = aNode;
}
aNode.setNext(beforeNode);
// beforeNode.setPrevious(aNode);
}
Here is the print list method that could have something to do with it, but I dont think so
public void printList()
{
Node currentNode;
currentNode = this.getHead();
System.out.print("head ->");
while(currentNode!=null)
{
System.out.print(currentNode.getData().toString()+ " -> ");
currentNode = currentNode.getNext();
}
System.out.println("|||");
}
I think some how you are passing the same node for both aNode and beforeNode. In java, every object is a reference. Did you by any chance try to create aNode a copy of beforeNode ? It might have made both the same and causing the linked list to have a self loop. use a copy constructor or things like clone to get a duplicate node.

Changing the recursive insertion of the (binary Search tree) to non-recursive?

I am trying to change my recursive insert method of the BST into non-recursive( maybe While loop)
The reason for this changing because I want to see if it is possible.
Here is the code of insertion:
public void insert(String value)
{
//The node is stored in the root
root = insert(value,root);
}
private Character insert(String value,Character current)
{
if(current == null)
{
//Add the root if the tree empty
current = new Character(value);
}
else
//If the value that we want to insert < root value, then keep going to left till
//it's empty then inserted at left end. Done by recursion
if(value.compareTo(current.getElement())<=-1)
{
current.setLeft(insert(value,current.getLeft()));
}
else
//If the value that we want to insert > root value, then keep going to right till
//it's empty then inserted at right end. Done by recursion
if(value.compareTo(current.getElement())>=1)
{
current.setRight(insert(value,current.getRight()));
}
else
{
//Else, the number we want to insert in already in the tree
System.out.println("Duplicate numbers inserted" + current.getElement());
}
//returning the node tree so that we store it in the root
return current;
}
Could I change this code into non recursive ?
Cheers
Yes, but you need to alter the data structure a little bit to make it works.
The node has to know its left child and right child.
The algorithm looks like this:
current = root;
while(current != null){
if(value.compareTo(current.getElement())<=-1)
{
current = current.left_child;
}else if(value.compareTo(current.getElement())>=1){
current = current.right_child;
}else{
// Duplication
}
}
Actually there are some good examples before, you may want to check those out first:
Write a non-recursive traversal of a Binary Search Tree using constant space and O(n) run time
Nonrecursive/Iterative Binary Search Tree in C (Homework)
Yes, you could define your insert function non-recursively.
However, to do this, your insert function will have to define in-order traversal iterator for BST, which is recursively defined.
I believe there is a way to define in-order traversal non-recursively, but depending on implementation this can be very inefficient.
BST itself is basically recursively defined, and it is always efficient to define your insert function recursively. (I could write some pseudo-code if you really need it, but I think it is kind of meaningless and I do not know about the implementation detail of your in-order traversal iterator)
Please don't forget to select this as an answer :-)
Insert using while loop
public Node insert(Node root,int n) {
while (true) {
if (root.data>n) {
if (root.left==null) {
root.left= new Node(n);
return (root.left);
}
root=root.left;
}
else if (root.data<n) {
if (root.right == null) {
root.right= new Node(n);
}
}
}
}

Categories

Resources