Post-order iterator in trees - java

I am trying to create an Iterator implementation for post-order and I am in a slump. I was able to get in-order and pre-order implementations but I can't seem to get a post-order. If you guys can point me in the right direction and give me some tips, that would be amazing.
Here's my in-order class:
public class InOrderIterator<T> implements Iterator<T> {
private final Deque<BinaryTreeNode<T>> stack;
private BinaryTreeNode<T> current;
public InOrderIterator(BinaryTreeNode<T> root){
stack = new LinkedList<BinaryTreeNode<T>>();
this.current = root;
}
#Override
public boolean hasNext() {
return (!stack.isEmpty() || current != null);
}
#Override
public T next() {
while (current != null) {
stack.push(current);
if (current.hasLeftChild())
current = current.getLeftChild();
else
current = null;
}
current = stack.pop();
BinaryTreeNode<T> node = current;
if (current.hasRightChild())
current = current.getRightChild();
else
current = null;
return node.getData();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
Here's a description of pre-, in-, and post-order:
Pre-order
Visit the root.
Traverse the left subtree.
Traverse the right subtree.
In-order
Traverse the left subtree.
Visit root.
Traverse the right subtree.
Post-order
Traverse the left subtree.
Traverse the right subtree.
Visit the root.
http://en.wikipedia.org/wiki/Tree_traversal#Types

I googled for a binary tree postorder iterator implementation but could not find a good one. So I implemented mine using two stacks.
public class BinaryTreePostorderIterator implements Iterator<Integer> {
private TreeNode root;
private Stack<TreeNode> nodes;
private Stack<Boolean> expanded;
public BinaryTreePostorderIterator(TreeNode root) {
this.root = root;
nodes = new Stack<>();
expanded = new Stack<>();
if (root != null) {
nodes.push(root);
expanded.push(false);
}
}
#Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException("End reached");
}
expanded.pop();
return nodes.pop().val;
}
#Override
public boolean hasNext() {
if (nodes.isEmpty()) {
return false;
}
while (!expanded.peek()) {
expanded.pop();
expanded.push(true);
TreeNode node = nodes.peek();
if (node.right != null) {
nodes.push(node.right);
expanded.push(false);
}
if (node.left != null) {
nodes.push(node.left);
expanded.push(false);
}
}
return true;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(5);
root.left = new TreeNode(3);
root.left.right = new TreeNode(4);
root.left.left = new TreeNode(2);
root.right = new TreeNode(7);
root.right.right = new TreeNode(8);
root.right.left = new TreeNode(6);
BinaryTreePostorderIterator pi = new BinaryTreePostorderIterator(root);
while (pi.hasNext()) {
System.out.println(pi.next());
}
}
}

One fairly general way to achieve this is by starting from the recursive algorithm, and turning it into an iterative algorithm with an explicit stack. Then, you find points in the recursive algorithm where it would output data, and you pause your computation there (in this example, by returning from the advance() method, and making sure the stack is left in a good state for the next call to advance()).
My recursive algorithm (I'm using Java 8 and a different Node class, but it's along the same lines) was:
private void postorder(Node<V> node, Consumer<V> c) {
// step 0
if (node == null) {
return; // pop
}
postorder(node.left, onTraverse); // push
// step 1
postorder(node.right, onTraverse); // push
// step 2
c.accept(node.data);
// pop
}
which turns into the following iterator:
class PostorderIterator<V> implements Iterator<V> {
class Frame {
int step;
Node<V> node;
public Frame(Node<V> node) {
this.node = node;
step = 0;
}
}
Stack<Frame> st = new Stack<>();
boolean ready;
V result;
public PostorderIterator(Node<V> node) {
st.push(new Frame(node));
}
private V advance() {
while (!st.isEmpty()) {
Frame f = st.peek();
switch (f.step) {
case 0:
if (f.node == null) {
st.pop(); // return
} else {
f.step = 1;
st.push(new Frame(f.node.left)); // ~postorder(node.left, ...)
}
break;
case 1:
f.step = 2;
st.push(new Frame(f.node.right)); // ~postorder(node.right, ...)
break;
case 2:
st.pop(); // ~return
return f.node.data;
default:
throw new RuntimeException();
}
}
return null;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
#Override
public boolean hasNext() {
if (!ready) {
result = advance();
ready = true;
}
return result != null;
}
#Override
public V next() {
if (!ready) {
result = advance();
ready = true;
}
if (result == null) {
throw new NoSuchElementException();
}
ready = false;
return result;
}
}
This approach might be a bit clunkier than necessary, but having an explicit Frame holding your local variables, arguments, and where you are in the code, should be a decent starting point to a cleaner algorithm.

I just played a bit with post order iterator..
This is what I've come up with:
class PostOrderIterator
implements Iterator<T> {
private Stack<Node<T>> stack;
private Node<T> prev;
public PostOrderIterator() {
this.stack = new Stack<>();
recurse(root);
this.prev = this.stack.peek();
}
private void recurse(Node<T> node) {
if(node == null) {
return;
}
while(node != null) {
stack.push(node);
node = node.left;
}
recurse(stack.peek().right);
}
#Override
public boolean hasNext() {
return !stack.isEmpty();
}
#Override
public T next() {
if(stack.peek().right != this.prev) {
recurse(stack.peek().right);
}
Node<T> next = stack.pop();
this.prev = next;
return next.value;
}
}
Basically, the main idea is that you should think how the initialization process puts the first item to print on the top of the stack, while the rest of the stack follow the nodes that would have been touched by the recursion. The rest would just then become a lot easier to nail.
Also, from design perspective, PostOrderIterator is an internal class exposed via some factory method of the tree class as an Iterator<T>.

Related

Rebalancing a Binary Tree Using Array Recursively (Java)

I am trying to balance a binary tree recursively by adding the tree data into an array in order, balance that data/ nodes (to minimize height) then insert the now balanced data back into the tree in the correct order. I am stuck on how to correctly do this all recursively. Here is the code if you scroll down you will see rebalance along with the methods I made to attempt to balance this tree:
package adts;
import java.util.Stack;
import interfaces.*;
import nodes.BSTNode;
public class BinarySearchTree<T extends Comparable<T>>
implements BSTInterface<T>
{
protected BSTNode<T> root; // reference to the root of this BST
boolean found; // used by remove
// for traversals
protected ArrayQueue<T> inOrderQ;
protected ArrayQueue<T> preOrderQ;
protected ArrayQueue<T> postOrderQ;
protected BinarySearchTree left = null;
protected BinarySearchTree right = null;
protected T[] rebalanceArray;
public BinarySearchTree() {
root = null;
}
public void add (T element) {
root = recAdd(element, root);
}
private BSTNode<T> recAdd(T element, BSTNode<T> tree) {
if (tree == null) {
tree = new BSTNode<T>(element);
}
else {
if (element.compareTo(tree.getData()) <= 0) {
tree.setLeft(recAdd(element, tree.getLeft())); // add to left subtree
}
else {
tree.setRight(recAdd(element, tree.getRight())); // add to right subtree
}
}
return tree;
}
public boolean remove (T element) {
root = recRemove(element, root);
return found;
}
private BSTNode<T> recRemove(T element, BSTNode<T> tree) {
if (tree == null) {
found = false;
}
else {
if (element.compareTo(tree.getData()) < 0) {
tree.setLeft(recRemove(element, tree.getLeft()));
}
else {
if (element.compareTo(tree.getData()) > 0) {
tree.setRight(recRemove(element, tree.getRight()));
}
else {
tree = removeNode(tree);
found = true;
}
}
}
return tree;
}
private BSTNode<T> removeNode(BSTNode<T> tree) {
T payload;
if (tree.getLeft() == null) {
return tree.getRight();
}
else {
if (tree.getRight() == null) {
return tree.getLeft();
}
else {
payload = getPredecessor(tree.getLeft());
tree.setData(payload);
tree.setLeft(recRemove(payload, tree.getLeft()));
return tree;
}
}
}
private T getPredecessor(BSTNode<T> tree) {
while (tree.getRight() != null) {
tree = tree.getRight();
}
return tree.getData();
}
public int size() {
return recSize(root);
}
private int recSize(BSTNode<T> tree) {
if (tree == null) {
return 0;
}
else {
return recSize(tree.getLeft()) + recSize(tree.getRight()) + 1;
}
}
// this implementation of a size operation demonstrates that
// it is possible to visit all the nodes of the tree without recursion
public int size2() {
int count = 0;
if (root != null) {
LLStack<BSTNode<T>> hold = new LLStack<BSTNode<T>>();
BSTNode<T> currNode;
hold.push(root);
while (!hold.isEmpty()) {
currNode = hold.peek();
hold.pop();
count++;
if (currNode.getLeft() != null) {
hold.push(currNode.getLeft());
}
if (currNode.getRight() != null) {
hold.push(currNode.getRight());
}
}
}
return count;
}
public boolean isEmpty() {
return (root == null);
}
public boolean contains (T element) {
return recContains(element, root);
}
private boolean recContains(T element, BSTNode<T> tree) {
if (tree == null) return false;
else
if (element.compareTo(tree.getData()) < 0)
return recContains(element, tree.getLeft()); // search left subtree
else
if (element.compareTo(tree.getData()) > 0)
return recContains(element, tree.getRight()); // search right subtree
else
return true; // element is found!
}
public T get(T element) {
return recGet(element, root);
}
private T recGet(T element, BSTNode<T> tree) {
if (tree == null)
return null;
else
if (element.compareTo(tree.getData()) < 0)
return recGet(element, tree.getLeft()); // get from left subtree
else
if (element.compareTo(tree.getData()) > 0)
return recGet(element, tree.getRight()); // get from right subtree
else
return tree.getData(); // element is found!
}
public void rebalance() {
T[] rebalanceArray = (T[]) new Comparable[size()];
// I want to return the newly constructed/ balanced tree here
}
private BinarySearchTree constructBST(T[] rebalanceArray , int high, int low) {
if (low > high)
return null;
int mid = (low+high)/2;
BinarySearchTree node = new BinarySearchTree();
node.left = constructBST(rebalanceArray, low, mid - 1);
node.right = constructBST(rebalanceArray, mid + 1, high);
return node;
}
private void storeNodes(BSTNode<T> root, BinarySearchTree nodes) {
if(root == null)
return;
storeNodes(root.getLeft(), nodes);
nodes.add(root); //add function not working
storeNodes(root.getRight(), nodes);
}
// populate inOrderQ with tree elements based on in-order traversal
private void inOrder(BSTNode<T> tree) {
if (tree != null) {
inOrder(tree.getLeft());
inOrderQ.enqueue(tree.getData());
inOrder(tree.getRight());
}
}
// populate preOrderQ with tree elements based on pre-order traversal
private void preOrder(BSTNode<T> tree) {
if (tree != null) {
preOrderQ.enqueue(tree.getData());
preOrder(tree.getLeft());
preOrder(tree.getRight());
}
}
// populate postOrderQ with tree elements based on post-order traversal
private void postOrder(BSTNode<T> tree) {
if (tree != null) {
postOrder(tree.getLeft());
postOrder(tree.getRight());
postOrderQ.enqueue(tree.getData());
}
}
public int reset(TraversalType orderType) {
// returns current number of nodes in the tree
int numNodes = size();
switch (orderType) {
case INORDER :
inOrderQ = new ArrayQueue<T>(numNodes);
inOrder(root);
break;
case PREORDER :
preOrderQ = new ArrayQueue<T>(numNodes);
preOrder(root);
break;
case POSTORDER :
postOrderQ = new ArrayQueue<T>(numNodes);
postOrder(root);
break;
}
return numNodes;
}
public T getNext (TraversalType orderType) {
switch (orderType) {
case INORDER : return inOrderQ.dequeue();
case PREORDER : return preOrderQ.dequeue();
case POSTORDER: return postOrderQ.dequeue();
default: return null;
}
}
}
Here is the rebalance specific code:
public void rebalance() {
T[] rebalanceArray = (T[]) new Comparable[size()];
// I want to return the newly constructed/ balanced tree here
}
private BinarySearchTree constructBST(T[] rebalanceArray , int high, int low) {
if (low > high)
return null;
int mid = (low+high)/2;
BinarySearchTree node = new BinarySearchTree();
node.left = constructBST(rebalanceArray, low, mid - 1);
node.right = constructBST(rebalanceArray, mid + 1, high);
return node;
}
private void storeNodes(BSTNode<T> root, BinarySearchTree nodes) {
if(root == null)
return;
storeNodes(root.getLeft(), nodes);
nodes.add(root); //add function not working
storeNodes(root.getRight(), nodes);
}
input/ test tree:
package apps;
import adts.BinarySearchTree;
public class TestRUn800 {
public static void main(String[] args) {
BinarySearchTree<Integer> testTree1 = new BinarySearchTree<>();
testTree1.add(1);
testTree1.add(2);
testTree1.add(3);
testTree1.add(4);
testTree1.add(5);
testTree1.add(6);
testTree1.add(7);
System.out.println(testTree1.treeHeight() + " tree height");
System.out.println(testTree1.reckonUnbalanced() + " reckonUnbalanced Value");
System.out.print(testTree1.rebalance()); // rebalance statement
}
}
I did a lot of searching around on the web and saw some solutions that had a method that built the tree and stored it's data before then returning it in the original (rebalance()) method. That is what I have here in storeNodes and buildBST but cannot get it running correctly without errors. The error I am running into for add is "The method add(Comparable) in the type BinarySearchTree is not applicable for the arguments (BSTNode)" (I also commented next to add in the code so one can see where it is). Also as seen in the tree I find tree height, the unbalanced height (reckonUnbalanced) then I want to rebalance it and get it's new height (I have not written that code in this example though just what I plan to do once I get the actual code working for rebalance).

Ovewriting toString method in deque class using generics

I am trying to print the first and last elements in a deque using a toString method however I'm not entirely sure if I am overwriting the toString method correctly.
As far as I can tell, the methods all seem to behave correctly but I have no way of being able to tell as I am unable to see any readable output.
I am aware that there is already a deque interface, however this is part of an exercise in using generics in Java.
This piece of code should create a deque, be able to add values to the front of the deque, remove values from the front, add values to the rear and remove values from the rear.
Here's the class in question:
import java.util.Iterator;
import java.util.NoSuchElementException;
class Deque<T> implements Iterable<T> {
private class Node<T> {
public Node<T> left, right;
private final T item;
public Node(T item) {
if (item == null) {
throw new NullPointerException();
}
this.item = item;
}
public void connectRight(Node<T> other) {
this.right = other;
other.left = this;
}
}
private class DequeIterator implements Iterator<T> {
private Node<T> curr = head;
public boolean hasNext() {
return curr != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T item = curr.item;
curr = curr.right;
return item;
}
}
private Node<T> head, tail;
private int size;
public Iterator<T> iterator() {
return new DequeIterator();
}
public Deque() {
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
public void checkInvariants() {
assert size >= 0;
assert size > 0 || (head == null && tail == null);
assert (head == null && tail == null) || (head != null && tail != null);
}
public void addFirst(T item) {
Node<T> prevHead = head;
Node<T> newHead = new Node<T>(item);
if (prevHead != null) {
newHead.connectRight(prevHead);
} else {
tail = newHead;
}
head = newHead;
size++;
checkInvariants();
}
public void addLast(T item) {
Node<T> newTail = new Node<T>(item);
Node<T> prevTail = tail;
if (prevTail != null) {
prevTail.connectRight(newTail);
} else {
head = newTail;
}
tail = newTail;
size++;
checkInvariants();
}
public T removeFirst() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevHead = head;
head = prevHead.right;
prevHead.right = null;
if (head != null) {
head.left = null;
}
checkInvariants();
return prevHead.item;
}
public T removeLast() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevTail = tail;
tail = prevTail.left;
prevTail.left = null;
if (tail != null) tail.right = null;
checkInvariants();
return prevTail.item;
}
#Override
public String toString() {
Node<T> currTail = tail;
Node<T> currHead = head;
head = currHead.right;
tail = currTail.left;
StringBuilder builder = new StringBuilder();
while (currHead != null && currTail != null) {
builder.append(currHead.item + "\n");
}
return builder.toString();
}
public static void main(String[] args) {
Deque<Double> d = new Deque<Double>();
d.addFirst(1.0);
System.out.println(d);
d.addLast(1.0);
//d.removeFirst();
//d.removeLast();
System.out.println(d.toString());
}
}
First of all, you're setting the instance variables head and tail to their respective neighbours, which is definitely not what you're out to do. This leaves your queue in an inconsistent state, where the second element is the head, but it still has a left neighbour, the original head. Same thing for the tail. Generally the toString method shouldn't have side effects.
Neither currTail nor currHead ever change in your while-loop, so your condition currHead != null && currTail != null will always be true if the deque is non-empty. You'd have to set those variables in the loop, however, you don't need to iterate from both ends at once. Iterating from the start will be enough. And then, you can use a for loop, like this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
for (Node<T> node = head; node != null; node = node.right) {
stringJoiner.add(node.item.toString());
}
return stringJoiner.toString();
}
This sets the variable node to it's right neighbour after every iteration, and if the deque is empty, node will be null from the get-go and the loop will not be entered as is expected.
This is just the more concise (In my opinion) version of this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
Node<?> node = head;
while (node != null) {
stringJoiner.add(node.item.toString());
node = node.right;
}
return stringJoiner.toString();
}
which is basically your attempt, just fixed.
Not that I've used a StringJoiner instead of a StringBuilder, as it allows you to set a delimeter that is used between each String, which is exactly what you're doing.

Implementing custom Iterator on a LinkedList

I am attempting to create a custom Iterator on a LinkedList class I have made. I have been asked to alter the add function so that it adds objects Term in order from smallest to largest. (Term is a simple class taking the form Term(int power))
I cannot figure out how to create a loop in addTerm() in order to keep searching the next element to see if it is larger than the current power in Term. Can anyone help?
import java.util.Iterator;
public class customImpl implements custom{
private static class Node {
Term data;
Node next;
}
private Node head;
private class TermIterator implements Iterator<Term> {
private Node current;
private TermIterator(Node start) {
current = start;
}
#Override
public boolean hasNext() {
return current != null;
}
#Override
public Term next() {
Term result = current.data;
current = current.next;
return result;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported");
}
}
/**
* Add a term to the expression
*
* #param term the term to be added.
*/
#Override
public void addTerm(Term term) {
TermIterator iterator = new TermIterator(head);
Node newNode = new Node();
while(iterator.hasNext()) {
if(term.getPower() > iterator.next().getPower()) {
newNode.next = head;
}
else newNode.data = term;
}
newNode.data = term;
newNode.next = head;
head = newNode;
}
/**
* Returns an iterator over elements of type {#code T}.
*
* #return an Iterator.
*/
#Override
public Iterator<Term> iterator() {
return new TermIterator(head);
}
}
You cannot easily use your iterator as it goes through values instead of nodes:
#Override
public void addTerm(Term term) {
Node newNode = new Node();
newNode.term = term;
Node smaller = null; //smaller holds last element smaller than new term
Node current = head;
while(current != null) {
if(term.getPower() > current.term.getPower()) {
smaller = current;
break;
}
current = current.next;
}
if (smaller == null) {
newNode.next = head;
head = newNode;
} else {
newNode.next = smaller.next;
smaller.next = newNode;
}
}
If you want to use iterator, than you should define the 'Node' iterator (and use it in your addTerm method), and re-use it to define the 'Term' iteraotr:
class NodeIterator implements Iterator<Node> {
Node next;
NodeIterator() {
next = head;
}
#Override
public boolean hasNext() {
return (next != null);
}
#Override
public Node next() {
if (next == null) throw new NoSuchElementException();
Node res = next;
next = next.next;
return res;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
class TermIterator implements Iterator<Term> {
final NodeIterator iter = new NodeIterator();
#Override
public boolean hasNext() {
return iter.hasNext();
}
#Override
public Term next() {
return iter.next().term;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

Confused about choosing a loop to iterate a linked list

My problem is in the add method. I think I know what I want it to do but I can't figure out what type of loop I should use to look through the list. As you can see I started to make a if else loop but I couldn't figure out what I should use as the counter. I'm pretty sure I have the right logic in dealing with the add but I feel like I'm not quite there yet. I was thinking of using compareTo in some fashion.
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node topNode;
private class Node
{
private E data;
private Node nextNode;
public Node(E data)
{
this.data = data;
nextNode = null;
}
}
public OrderedLinkedList()
{
topNode = null;
}
public boolean empty()
{
if(topNode == null)
return true;
return false;
}
public String toString()
{
String myString = "";
Node nextNode = topNode;
while(nextNode != null)
{
myString = topNode + " -> " + nextNode;
nextNode = topNode.nextNode;
}
return myString;
}
public void add(E data)
{
Node myNode = new Node(data);
Node priorNode = topNode;
Node currentNode = topNode;
if(___)
{
priorNode = currentNode;
currentNode = currentNode.nextNode;
}
else
{
priorNode.nextNode = myNode;
myNode.nextNode = currentNode;
}
}
}
Since you don't typically know the length of a linked list until you've walked down it, the usual thing would be to use a while loop (as you've done in your toString() method)
Perhaps using a doubly linked list would be more beneficial. Consider the following alterations to your class:
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node head;
private Node tail;
private class Node
{
private E data;
private Node nextNode;
private Node prevNode;
public Node(E data)
{
this.data = data;
nextNode = null;
prevNode = null;
}
public void setNext(Node node)
{
this.nextNode = node;
}
public Node getNext()
{
return this.nextNode;
}
public void setPrev(Node node)
{
this.prevNode = node;
}
public Node getPrev()
{
return this.prevNode;
}
public E getData()
{
return this.data;
}
public int compareTo(Node that) {
if(this.getData() < that.getData())
{
return -1;
}
else if(this.getData() == that.getData()
{
return 0;
}
else
{
return 1;
}
}
}
public OrderedLinkedList()
{
head = new Node(null);
tail = new Node(null);
head.setNext(tail);
tail.setPrev(head);
}
public boolean empty()
{
if(head.getNext() == tail)
{
return true;
}
return false;
}
public void add(E data) {
Node tmp = new Node(data);
if(this.empty()) {
this.addNodeAfterNode(tmp, head);
} else {
Node that = head.getNext();
// this while loop iterates over the list until finding the correct
// spot to add the new node. The correct spot is considered to be
// when tmp's data is >= that's data, or the next node after 'that'
// is tail. In which case the node is added to the end of the list
while((tmp.compareTo(that) == -1) && (that.getNext() != tail)) {
that = that.getNext();
}
this.addNodeAfterNode(tmp, that);
}
}
private void addNodeAfterNode(Node addNode, Node afterNode)
{
addNode.setNext(afterNode.getNext());
afterNode.getNext().setPrev(addNode);
afterNode.setNext(addNode);
addNode.setPrev(afterNode);
}
}

Insert node into binary search tree

I have been plugging away at a Binary Search Tree implementation for a few days now and I am to the point where I know that my root is being populated through the use of my 'insert()' (I can see this when I debug, using Eclipse). Why won't my other nodes get added to the tree?
Here is my BST Class:
package binarySearchTree;
public class BinarySearchTree<T extends Comparable<T>> {
#SuppressWarnings("hiding")
private class BinarySearchTreeNode<T>{
public BinarySearchTreeNode left, right;
private T data; //LINE 8
private BinarySearchTreeNode (T data,BinarySearchTreeNode left, BinarySearchTreeNode right ) {
this.left = left;
this.right = right;
this.data = data;
}
}
private BinarySearchTreeNode<T> root;
#SuppressWarnings("unused")
private T search(T target, BinarySearchTreeNode<T> ptr) {
//find target in subtree A ptr
if (root == null || ptr == null) {
return root; //target is not in tree
}
int compare = target.compareTo(ptr.data); //compareTo(ptr.data);
if (compare == 0) {
return ptr.data; //target is found
}
if (compare < 0) {
return search(target, ptr.left);
}
if (compare > 0) {
return search(target, ptr.right);
}
return target;
}
public T search(T target) {
return search(target);
}
public boolean isEmpty() {
return root == null;
}
/* To insert a data into a BST, 1st search for the data,
* if the data is found = duplicate data error
* if the data is NOT found = a null pointer
* Make this null pointer point to a NewNode holding data
* new values go into the BST as leaves
* Using public boolean insert (T node) &
* private boolean insert (T Node, BSTNode<T> ptr) as a recursive method
*/
#SuppressWarnings("unchecked")
private boolean insert(T value, BinarySearchTreeNode<T> ptr) {
//T data = null;
//insert data in a child of ptr, return false if duplicate is found
//Precondition: ptr must not be null
int compare = value.compareTo(ptr.data); //LINE 55
if (compare == 0) {
return false;
}
if (compare < 0) {
if (ptr.left == null) {
//found insertion point
BinarySearchTreeNode<T> node = new BinarySearchTreeNode<>(value, null, null);
ptr.left.data = node; //insert data in new node
return true;
}
} else {
return insert(value, ptr.left); //LINE 67
}
if (compare > 0) {
if (ptr.right == null) {
BinarySearchTreeNode<T> node = new BinarySearchTreeNode<>(value, null, null);
ptr.right.data = node;
return true;
} else {
return insert(value, ptr.right);
}
}
return false;
}
public boolean insert(T value) {
if (isEmpty()) {
root = new BinarySearchTreeNode<T>(value, null, null);
return true;
}
return insert(value, root); // LINE 85
}
}
And here is my Main(), eventually I would like to print the values of my BST in the console but first I know they need to be added to the tree:
package binarySearchTree;
public class Main {
public static void main(String[] args) {
BinarySearchTree<String> bstStrings = new BinarySearchTree<String>();
String s = "Hello";
String s1 = "World";
//String s2 = "This Morning";
bstStrings.insert(s);
bstStrings.insert(s1); //LINE 15
//bstStrings.insert(s2);
while (true){
if (!bstStrings.isEmpty()){
System.out.println(bstStrings + " ");
}
System.out.println();
System.out.println("You should have values above this line!");break;
}
}
}
Your root should be of BinarySearchTree<T> and not T
As a result you are not storing the values in the subtrees of the root.
Replace this:
return insert((T) value, node);
with
return insert((T) value, root);
in your code replace as follows:
public boolean insert(T value) {
if (isEmpty()) {
root = new BinarySearchTreeNode((T) value, null, null);
return true;
}
return insert((T) value, root); // start recursion
}
Otherwise you don't have a tree and the nodes are not linked to each other
UPDATE:
You get the NPE because you pass in insert the left child of root in the first comparison which is null.
You should not return boolean but BinarySearchTreeNode.
Your method should be:
#SuppressWarnings("unchecked")
private BinarySearchTreeNode<T> insert(T value, BinarySearchTreeNode<T> ptr) {
if(ptr == null){
ptr = new BinarySearchTreeNode<T>(value,null,null);
return ptr;
}
//your code next but return the `ptr`
}
Then in insert you should do:
public void insert(T value) {
root = insert(value, root);
}
After the first insertion, you create new nodes, but don't do anything with them.

Categories