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).
Related
I've just created a method to test the height of my binary tree implementation as follows:
public int height() {
return height(rootNode);
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
But it returns a height of 6, and not 7 when i add the nodes 1-6.
Here is my Binary Tree code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E extends Comparable<E>>
{
private class BinaryTreeNode
{
private E value;
private BinaryTreeNode leftChild, rightChild;
public BinaryTreeNode(E value) {
this(value, null, null);
}
public BinaryTreeNode(E value, BinaryTreeNode leftChild, BinaryTreeNode rightChild) {
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public E getValue() {
return value;
}
public BinaryTreeNode getLeftChild() {
return leftChild;
}
public BinaryTreeNode getRightChild() {
return rightChild;
}
public void setLeftChild(BinaryTreeNode newLeftChild) {
this.leftChild = newLeftChild;
}
public void setRightChild(BinaryTreeNode newRightChild) {
this.rightChild = newRightChild;
}
}
private BinaryTreeNode rootNode;
public BinaryTree() {
this.rootNode = null;
}
public void addNode(E value) {
if(rootNode == null)
rootNode = new BinaryTreeNode(value);
else
addNode(value, rootNode);
}
//TODO: Implement removeNode()
public void printLevelOrder() {
printLevelOrder(rootNode);
}
public int height() {
return height(rootNode);
}
public void inOrderTraversal() {
if(rootNode != null) inOrderTraversal(rootNode);
else System.out.println("The tree is empty!");
}
private void addNode(E value, BinaryTreeNode node) {
if(node.getValue().compareTo(value) > 0) {
if(node.getLeftChild() != null)
addNode(value, node.getLeftChild());
else
node.setLeftChild(new BinaryTreeNode(value));
} else {
if(node.getRightChild() != null)
addNode(value, node.getRightChild());
else
node.setRightChild(new BinaryTreeNode(value));
}
}
private void printLevelOrder(BinaryTreeNode node) {
Queue<BinaryTreeNode> currentLevel = new LinkedList<BinaryTreeNode>();
Queue<BinaryTreeNode> nextLevel = new LinkedList<BinaryTreeNode>();
currentLevel.add(node);
while (!currentLevel.isEmpty()) {
Iterator<BinaryTreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
BinaryTreeNode currentNode = iter.next();
if (currentNode.leftChild != null) {
nextLevel.add(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nextLevel.add(currentNode.rightChild);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<BinaryTreeNode>();
}
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
private void inOrderTraversal(BinaryTreeNode node) {
if(node != null) {
inOrderTraversal(node.leftChild);
System.out.println(node.getValue() + " ");
inOrderTraversal(node.getRightChild());
}
}
public BinaryTreeNode getRoot() {
return rootNode;
}
}
I think the problem is adding my node into the tree, but I've taken a look at other examples but they all seem to be doing the same thing I am.. So i can't realise the problem!
Thanks!
private int height(BinaryTreeNode node) {
if(node == null) return 0;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
You were returning -1 on node==null when you should return 0.
The condition is true when we arrive to leaf so for example if we add 1-2 then we have height as 1+Max(leftof(1),rightof(1))=
1+Max(height(null),height(2))=
1+Max(0,1+Max(leftof(2),rightof(2)))=
1+Max(0,1+Max(height(null),height(null)))=
1+Max(0,1+Max(0,0))=
1+Max(0,1+0)=
1+1=2.
Try to replace height(null) with -1 in the previous example to see by yourself.
By the way your BinaryTree implementation is actually a binary search tree since you're putting less elements on the left and bigger elements on the right, If a search tree is your intention then Ok but if you want to implement a general binary tree then you should change the add function.
So the idea is to make a Double Ended Priority Queue so far I have got a tree like structure using 2 Linked Lists, I have and interface I have to stick with with no alterations to it. The problem I have got is I have to make 2 methods called getMost and getLeast which gets the most or least node and then makes that node null. But these 2 methods are proving quite difficult to make. How would you go about doing it?
I have tried using recursion but this is proving difficult as I have to select the tree by going tree.root but passing in tree.root into a recursive method always starts it from tree.root
Also I have tried what i have written in inspectLeast() and inspectMost() but Java passes by value not by reference. Any tips?
P.S Not allowed to use anything from java collections or java util.
public class PAS43DPQ implements DPQ
{
//this is the tree
TreeNode tree = new TreeNode();
//this is for the size of the array
int size = 0;
#Override
public Comparable inspectLeast() {
return tree.inspectLeast(tree.root);
}
#Override
public Comparable inspectMost() {
return tree.inspectMost(tree.root);
}
#Override
public void add(Comparable c)
{
tree.add(c);
size++;
}
#Override
public Comparable getLeast() {
if (tree.root != null){
}
return getLeast();
}
#Override
public Comparable getMost(){
Comparable most = getMost();
return most;
}
#Override
public boolean isEmpty() {
return (size > 0)?true:false;
}
#Override
public int size() {
return this.size;
}
class TreeNode{
private Comparable value;
private TreeNode left, right, root;
//constructors
public TreeNode() {}
public TreeNode(TreeNode t) {
this.value = t.value;
this.left = t.left;
this.right = t.right;
this.root = t.root;
}
public TreeNode(Comparable c) {
this.value = (int) c;
}
public void add(Comparable input){
if(root == null){
root = new TreeNode(input);
return;
} else {
insert(root, input);
}
}
public Comparable inspectLeast(TreeNode n){
if (n == null)
return null;
if (n.left == null){
TreeNode least = n;
return least.value;
}
return inspectLeast(n.left);
}
public Comparable inspectMost(TreeNode n){
if (n == null)
return null;
if (n.right == null){
TreeNode most = n;
return most.value;
}
return inspectMost(n.right);
}
public Comparable getMost(TreeNode n){
if(n.right == null)
return n.value;
return tree.getMost(right);
}
public void insert(TreeNode n, Comparable input){
if(input.compareTo(n.value) >= 0){
if (n.right == null) {
n.right = new TreeNode(input);
return;
}
else
insert(n.right, input);
}
if(input.compareTo(n.value) < 0){
if(n.left == null) {
n.left = new TreeNode(input);
return;
}
else
insert(n.left, input);
}
}
}
}
You should be able to modify your TreeNode.getMost(TreeNode n) and TreeNode.getLeast(TreeNode n) similar to the following:
public class TreeNode{
// Also, your parameter here seems to be superfluous.
public TreeNode getMost(TreeNode n) {
if (n.right == null) {
n.root.right = null;
return n;
}
return n.getMost(n);
}
}
Get least should be able to be modified in a similar fashion, but using left rather than right obviously.
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>.
I am trying to quickly implement a Binary search tree in Java. What is the best class to use that has methods for in-order traversal?
(I have heard of TreeMap class. But it looks like the class does not contain any methods to do in-order traversal).
Use LinkedHashMap to traverse in insertion order or TreeMap to traverse in comparison order
http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
You could always just make your own class and that implements the algo using said class.
public class Node {
Node leftChild;
Node rightChild;
int parent;
Node(int parent) {
this.parent = parent;
}
}
And then implement the Binary Search Tree class. This was made very fast, but it's to give you an idea.
public class BSTree {
Node root;
BSTree() {
root = null;
}
public void insert(Node node, int value) {
if (value >= node.parent) {
if (!(node.rightChild == null)) {
insert(node.rightChild, value);
} else {
node.rightChild = new Node(value);
}
} else if (value < node.parent) {
if (!(node.leftChild == null)) {
insert(node.leftChild, value);
} else {
node.leftChild = new Node(value);
}
} else {
root = new Node(value);
}
}
public boolean delete(Node node, int value) {
if (root == null) {
return false;
} else if (value > root.parent) {
return delete(root.rightChild, value);
} else if (value < root.parent) {
return delete(root.leftChild, value);
} else {
if (root.leftChild == null && root.rightChild == null) {
root = null;
return true;
} else if (root.leftChild == null && root.rightChild != null) {
root = root.rightChild;
return true;
} else if (root.leftChild != null && root.rightChild == null) {
root = root.leftChild;
return true;
} else {
Node minRight = minNode(root.rightChild);
root = minRight;
delete(minRight, minRight.parent);
return true;
}
}
}
public Node minNode(Node node) {
if (node.leftChild == null) {
return node;
} else {
return minNode(node.leftChild);
}
}
}
The TreeSet class might be what you want
class Node implements Comparable<Node>; // implements your Node class
TreeSet<Node> set = new TreeSet<Node>();
// after adding a bunch of nodes into set
Iterator<Node> it = set.iterator();
while(it.hasNext()){
Node current = it.next();
System.out.println(current); // operate on current node
}
Node first = set.first(); // smallest element in set
Node second = set.ceiling(first); // the successor method
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.