Simple binary search tree in Java - java

Here there is code for a simple BST in Java that keys are only int, but when I want to test it and use print() just root.key can be printed and root.right and root.left are null.
public class BST {
private class Node {
private int key;
private Node left, right;
public Node(int key) {
this.key = key;
}
}
private Node root;
public BST(int key) {
root = new Node(key);
}
public void insert(int key) {
insert(root, key);
}
private void insert(Node x, int key) {
if (x == null) {
x = new Node(key);
}
if (key > x.key) {
insert(x.right, key);
} else if (key < x.key) {
insert(x.left, key);
} else {
x.key = key;
}
}
public void print() {
print(root);
}
private void print(Node x) {
System.out.print(x.key + " ");
if (x.left != null)
print(x.left);
if (x.right != null)
print(x.right);
}
}
For example, when I insert 25, 9, 10, 30, 40 and call print() then it just prints 25.

x = new Node(key);
This assignment basically throws away the new Node, because x is just a local variable. You are not modifying the callers reference here, you are just modifying the local copy of the reference the caller gave you. What you could do is return the x and have the caller assign it:
x = insert(x, 3);
The insert would then look something like this:
private Node insert(Node x, int key) {
if (x==null){
return new Node(key);
}
if (key > x.key) {
x.right = insert(x.right, key);
}else if (key < x.key) {
x.left = insert(x.left, key);
}else{
x.key = key;
}
return x;
}

Related

Delete all entries with a given value in AVL Tree

I am implementing an AVL Tree of the following type AVLTree<K extends Comparable<K>,V> basically every node of the Tree is a Key-Value Node, at the moment i am struggling with a method that deletes all the V values. This is what i have:
private void deleteAll(AVLTreeNode<K,V> root, V value){
if(root == null) return;
deleteAll(root.left, value);
deleteAll(root.right, value);
if(root.getValue().equals(value)){
delete(root.getKey());
}
}
Super easy approach (maybe not optimized O(nlog(n)) if you have a better optimized solution feel free to write it) using a bottom-up recursion.
The delete method:
public void delete(K key){
super.setRoot(delete(super.getRoot(), key));
}
private AVLTreeNode<K,V> delete(AVLTreeNode<K,V> root, K key) {
if (root == null) {
return root;
} else if (root.getKey().compareTo(key) > 0) {
root.setLeft(delete(root.left, key));
} else if (root.getKey().compareTo(key) < 0) {
root.setRight(delete(root.right, key));
} else {
if (root.left == null || root.right == null) {
root = (root.left == null) ? root.right : root.left;
} else {
AVLTreeNode<K,V> mostLeftChild = AVLTreeUtils.minValueNode(root.right);
root.key = mostLeftChild.getKey();
root.value = mostLeftChild.getValue();
root.setRight(delete(root.right, root.key));
}
size--;
}
if (root != null) {
root = AVLTreeUtils.rebalance(root);
}
return root;
}
What happens is that it deletes correclty most of the values but sometimes it lefts some of the values it had to delete there, here is one example:
DELETING ALL VALUES: 2
BEFORE DELETION OF EVERY: 2
->2
->0
->1
->2
->1
->1
->1
->0
->2
->2
AFTER DELETION
->2
->0
->1
->2
->1
->1
->1
->0
Time used: 0 ms tree size: 8
-------------------------------------------
Does tree contain value: 2? true
EDIT:
Here is all the code of the class
package structure.tree.balanced;
import structure.array.Array;
import structure.node.Node;
import structure.tree.Tree;
public class AVLTree<K extends Comparable<K>,V> extends Tree<AVLTree.AVLTreeNode<K, V>> {
private static final long serialVersionUID = 5046115177325966348L;
public boolean containsValue(V value) {
return containsValue(((AVLTreeNode<K,V>) super.getRoot()), value);
}
private boolean containsValue(AVLTreeNode<K,V> root, V value){
if(root == null) return false;
else {
if(root.getValue().equals(value)) return true;
else return containsValue(root.getLeft(), value) || containsValue(root.getRight(), value);
}
}
public boolean containsKey(K key){
return containsKey(((AVLTreeNode<K,V>) super.getRoot()), key);
}
private boolean containsKey(AVLTreeNode<K,V> root, K key){
if(root == null) return false;
else {
if(root.getKey().compareTo(key) < 0) return containsKey(root.getRight(), key);
else if(root.getKey().compareTo(key) > 0) return containsKey(root.getLeft(), key);
else return true;
}
}
public void delete(K key){
super.setRoot(delete(super.getRoot(), key));
}
private AVLTreeNode<K,V> delete(AVLTreeNode<K,V> root, K key) {
if (root == null) {
return root;
} else if (root.getKey().compareTo(key) > 0) {
root.setLeft(delete(root.left, key));
} else if (root.getKey().compareTo(key) < 0) {
root.setRight(delete(root.right, key));
} else {
if (root.left == null || root.right == null) {
root = (root.left == null) ? root.right : root.left;
} else {
AVLTreeNode<K,V> mostLeftChild = minValueNode(root.right);
root.key = mostLeftChild.getKey();
root.value = mostLeftChild.getValue();
root.setRight(delete(root.right, root.key));
}
if(size > 0) size--;
}
if (root != null) {
root = rebalance(root);
}
return root;
}
public void deleteAll(V value){
deleteAll(super.getRoot(), value);
}
private void deleteAll(AVLTreeNode<K,V> root, V value){
if(root == null) return;
deleteAll(root.left, value);
deleteAll(root.right, value);
if(root.getValue().equals(value)) delete(root.getKey());
}
public V get(K key){
return get(super.getRoot(), key);
}
private V get(AVLTreeNode<K, V> root, K key) {
if(root.getKey().compareTo(key) == 0) return root.getValue();
else if(root.getKey().compareTo(key) > 0) return get(root.getLeft(), key);
else return get(root.getRight(), key);
}
private int getBalance(AVLTreeNode<K,V> n) {
return (n == null) ? 0 : height(n.getRight()) - height(n.getLeft());
}
private int height(AVLTreeNode<K,V> n) {
return n == null ? -1 : n.getHeight();
}
public void insert(K key, V value) {
size++;
super.setRoot(insert(super.getRoot(), key, value));
}
private AVLTreeNode<K,V> insert(AVLTreeNode<K,V> root, K key, V value){
if (root == null) {
return new AVLTreeNode<K,V>(key, value);
} else if (root.getKey().compareTo(key) > 0) {
root.setLeft(insert(root.getLeft(), key, value));
} else if (root.getKey().compareTo(key) < 0) {
root.setRight(insert(root.getRight(), key, value));
} else {
size--;
throw new RuntimeException("duplicate Key!");
}
return rebalance(root);
}
private AVLTreeNode<K,V> minValueNode(AVLTreeNode<K,V> root){
if(root == null) return null;
else {
if(root.getLeft() != null) return minValueNode(root.getLeft());
else return root;
}
}
private AVLTreeNode<K,V> rebalance(AVLTreeNode<K,V> z) {
updateHeight(z);
int balance = getBalance(z);
if (balance > 1) {
if (height(z.getRight().getRight()) > height(z.getRight().getLeft())) {
z = rotateLeft(z);
} else {
z.setRight(rotateRight(z.getRight()));
z = rotateLeft(z);
}
} else if (balance < -1) {
if (height(z.getLeft().getLeft()) > height(z.getLeft().getRight()))
z = rotateRight(z);
else {
z.setLeft(rotateLeft(z.getLeft()));
z = rotateRight(z);
}
}
return z;
}
public void replace(K key, V newValue) {
replace(super.getRoot(), key, newValue);
}
private void replace(AVLTreeNode<K, V> root, K key, V newValue) {
if(root != null){
if(root.getKey().compareTo(key) == 0) root.setValue(newValue);
else if(root.getKey().compareTo(key) > 0) replace(root.getLeft(), key, newValue);
else replace(root.getRight(), key, newValue);
}
}
public void replaceAll(V oldValue, V newValue){
replaceAll(super.getRoot(), oldValue, newValue);
}
private void replaceAll(AVLTreeNode<K, V> root, V oldValue, V newValue){
if(root == null) return;
if(root.getValue().equals(oldValue)) root.setValue(newValue);
replaceAll(root.left, oldValue, newValue);
replaceAll(root.right, oldValue, newValue);
}
private AVLTreeNode<K,V> rotateLeft(AVLTreeNode<K,V> y){
AVLTreeNode<K,V> x = y.getRight();
AVLTreeNode<K,V> z = x.getLeft();
x.setLeft(y);
y.setRight(z);
updateHeight(y);
updateHeight(x);
return x;
}
private AVLTreeNode<K,V> rotateRight(AVLTreeNode<K,V> y){
AVLTreeNode<K,V> x = y.getLeft();
AVLTreeNode<K,V> z = x.getRight();
x.setRight(y);
y.setLeft(z);
updateHeight(y);
updateHeight(x);
return x;
}
public Object[] toArray(){
return toArray(super.getRoot(), new Array<>(size()));
}
private Object[] toArray(AVLTreeNode<K,V> root, Array<AVLTreeNode<K,V>> arr){
if(root != null){
toArray(root.left, arr);
arr.insert(root);
toArray(root.right, arr);
}
return arr.toArray();
}
private void updateHeight(AVLTreeNode<K,V> root){
root.setHeight(1 + Math.max(height(root.getLeft()), height(root.getRight())));
}
public static class AVLTreeNode<K extends Comparable<K>, V> implements Node<V> {
private static final long serialVersionUID = -2099221188924293375L;
private AVLTreeNode<K,V> left, right;
private K key;
private V value;
private int height = 0;
public AVLTreeNode(K key, V value){
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
#SuppressWarnings("unused")
private void setKey(K key) {
this.key = key;
}
public AVLTreeNode<K,V> getLeft() {
return left;
}
protected void setLeft(AVLTreeNode<K,V> left) {
this.left = left;
}
public AVLTreeNode<K,V> getRight() {
return right;
}
protected void setRight(AVLTreeNode<K,V> right) {
this.right = right;
}
#Override
public String toString() {
return "{\"key\":"+key+",\"value\":"+getValue()+"}";
}
#Override
public V getValue() {
return value;
}
#Override
public void setValue(V value) {
this.value = value;
}
public int getHeight() {
return height;
}
protected void setHeight(int height) {
this.height = height;
}
public int getBalance() {
return (left != null ? left.getHeight() : 0) - (right != null ? right.getHeight() : 0);
}
}
}
The superclass is this:
package structure.tree;
import structure.Structure;
import structure.node.Node;
/**
* A Tree is a {#Structure} that uses {#Node} as value.
*/
public abstract class Tree<N extends Node<?>> {
private static final long serialVersionUID = -2524427972418434522L;
private N root;
public void clear() {
root = null;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public N getRoot() {
return root;
}
protected void setRoot(N value) {
this.root = value;
}
}
This is the code i run that gives problems note that sometimes it works and sometimes it doesnt:
AVLTree<Integer,Integer> avlt = new AVLTree<Integer,Integer>();
Random r = new Random();
for(int i = 1; i <= SIZE; i++){
avlt.insert(i, r.nextInt(keySize));
}
int vdel = r.nextInt(keySize);
avlt.deleteAll(vdel);
assertEquals(false, avlt.containsValue(vdel));
The problem is that the tree structure changes whilst you are trying to find nodes to delete.
Consider this tree, from which we will be deleting the 'X's:
2->X
/ \
1->X 3->X
\
4->O
The delete operation starts at '2'. As the '2' node has a left hand branch, we descend to the '1' node. The '1' node has neither left nor right branches so there is no further descent.
Node '1' must be deleted.
2->X
\
3->X
\
4->O
And then the tree needs rebalancing.
3->X
/ \
2->X 4->O
This completes the processing of the '1' node, so the recursive search moves back to '2'.
The left hand branch has been processed. Due to the rebalancing, there is no longer a right hand branch to process. The '2' node itself needs deleting.
3->X
\
4->O
This completes the processign of node '2' so we return. This completes the algorithm.
Nodes '3' and '4' were never inspected because of the rebalancing.
How to fix this?
The easiest solution is to separate the search from the "delete and rebalance" operation. Create a collection of all the keys that map to the value to be deleted. Once all such keys are identified, delete those mappings one at a time. As the tree does not change shape during the search, the search will find all the relevant key-value pairs.
My own preference would be to create an Iterator over the tree nodes that supports remove. Such an Iterator would be useful for tasks beyond deleting matching values. For such an iterator one needs to be able to identify the next node from any specified node. This means a node has to know what its parent is.
To that end, I suggest amending your code as follows:
The node implementation tracks its parent and its key cannot be changed.
public static class AVLTreeNode<K extends Comparable<K>, V> implements Node<V> {
private AVLTreeNode<K,V> left, right, parent;
private final K key;
private V value;
private int height = 0;
public AVLTreeNode(K key, V value){
this.key = key;
this.value = value;
}
protected void setLeft(AVLTreeNode<K,V> left) {
this.left = left;
if( left!=null ) {
left.parent = this;
}
}
public AVLTreeNode<K,V> getNext() {
AVLTreeNode<K,V> next;
// If a right branch exists, the next node is the left-most node in the right branch.
if( right!=null ) {
next = right;
while( next.left!=null ) {
next = next.left;
}
return next;
}
// The closest parent of which this is a left-branch descendant is the next node
next = this;
while( next.parent!=null ) {
if( next.parent.left==next ) {
return next.parent;
}
next = next.parent;
}
// no next node
return null;
}
protected void setRight(AVLTreeNode<K,V> right) {
this.right = right;
if( right!=null ) {
right.parent = this;
}
}
... rest of class is unchanged
}
The tree's insert and delete method can move a node to the root of the tree, so they also have to set the node's parent to null if that happens.
public void insert(K key, V value) {
size++;
AVLTreeNode<K,V> newRoot = insert(super.getRoot(),key,value);
newRoot.parent = null;
super.setRoot(newRoot);
}
public void delete(K key){
AVLTreeNode<K,V> newRoot = delete(super.getRoot(), key);
if( newRoot!=null ) {
newRoot.parent = null;
}
super.setRoot(newRoot);
}
The delete method changed the key of a node, moving it out of sequence. To preserve the sequence it cannot do that.
private AVLTreeNode<K,V> delete(AVLTreeNode<K,V> root, K key) {
if (root == null) {
return root;
} else if (root.getKey().compareTo(key) > 0) {
root.setLeft(delete(root.left, key));
} else if (root.getKey().compareTo(key) < 0) {
root.setRight(delete(root.right, key));
} else {
if (root.left == null || root.right == null) {
root = (root.left == null) ? root.right : root.left;
} else {
// Promote the next node to replace root.
AVLTreeNode<K,V> mostLeftChild = minValueNode(root.right);
mostLeftChild.setRight(delete(root.right, mostLeftChild.key));
mostLeftChild.setLeft(root.left);
root = mostLeftChild;
}
if(size > 0) size--;
}
if (root != null) {
root = rebalance(root);
}
return root;
}
Then we can create an Iterator:
public static class AVLNodeIterator<K extends Comparable<K>,V> implements Iterator<AVLTreeNode<K,V>> {
AVLTree<K,V> tree;
AVLTreeNode<K,V> current;
AVLTreeNode<K,V> next;
public AVLNodeIterator(AVLTree<K,V> tree) {
this.tree = tree;
current = null;
next = tree.minValueNode(tree.getRoot());
}
#Override
public boolean hasNext() {
return next!=null;
}
#Override
public AVLTreeNode<K, V> next() {
if( next==null ) {
throw new NoSuchElementException();
}
current = next;
next = current.getNext();
return current;
}
#Override
public void remove() {
if( current==null ) {
throw new IllegalStateException();
}
tree.delete(current.getKey());
current=null;
}
}
and finally we can rewrite deleteAll to use the new iterator:
public void deleteAll(V value){
Iterator<AVLTreeNode<K,V>> iterator = new AVLNodeIterator<>(this);
while( iterator.hasNext()) {
AVLTreeNode<K,V> node = iterator.next();
if( node.getValue().equals(value) ) {
iterator.remove();
}
}
}

I need to implement a method where I can get key from value and method delete

I have a class MapEntry to implement Hashmap. I need to implement a method where I can get key from value and method delete. I know that HashMap does not implement such method as getValue but my prof asked to do this. I'm new to programming how it's a little bit hard for me right now. I'll appreciate any help.
public class MapEntry<K,V> {
MapEntry<K,V> next;
K key;
V value;
public MapEntry(K key, V value) {
this.setKey(key);
this.setValue(value);
}
public void setKey( K key){
this.key=key;
}
public void setValue(V value){
this.value=value;
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
public void setNext(MapEntry<K,V> next) {
this.next = next;
}
public MapEntry<K, V> getNext() {
return next;
}
}
public class HashMap{
private int DEFAULT_CAPACITY = 10;
private MapEntry<String,Double>[] Hash;
private int size;
public HashMap() {
Hash = new MapEntry[DEFAULT_CAPACITY];
}
public boolean isEmpty(){
if(size!= 0){
return false;
}
else{
return true;
}
}
public int getHashCode(String key){
int bucketIndex = key.hashCode()%Hash.length;
return bucketIndex;
}
public Double get(String key){
if(key == null){
try {
throw new IllegalAccessException("Null key");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
MapEntry<String,Double> entry = Hash[getHashCode(key)];
while (entry != null && !key.equals(entry.getKey()))
entry = entry.getNext();
if(entry != null)
return entry.getValue();
else
return null;
}
}
public void put(String key, double value){
int keyBucket =hash(key);
MapEntry<String,Double> temp = Hash[keyBucket];
while (temp !=null){
if((temp.key == null && key == null)
|| (temp.key != null && temp.key.equals(key))){
temp.value = value;
return;
}
temp = temp.next;
}
Hash[keyBucket] = new MapEntry<String, Double>(key,value);
size++;
}
public void delete (String key) throws IllegalAccessException {
if(key == null){
throw new IllegalAccessException("Null key");
}
}
private int hash(String key){
if(key == null){
return 0;
}else {
return Math.abs(key.hashCode()% this.Hash.length);
}
}
public static void main(String[] args) {
HashMap hashMap = new HashMap();
hashMap.put("value", 2.2);
hashMap.put("bob", 2.3);
System.out.println(hashMap.get("value"));
System.out.println(hashMap.get("bob"));
System.out.println(hashMap.size);
System.out.println(hashMap.getHashCode("value"));
System.out.println(hashMap.getHashCode("bob"));
System.out.println(hashMap.isEmpty());
}
}
I think the basic algo will be :
Iterate through all the values one by one
If your value matches the desired result, retrieve the key from that entry.
To delete that entry, simply remove that entry
Note : Doesn't work properly if you have multiple entries of same value.

Is my Binary Tree adding nodes properly?

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.

Binary Search Tree insertion - root remains null

I'm new to Java, I want to create a Binary Search Tree class with insertion and preorder traversal, but when I finish the insertion the root object remains null and the compiler throws NullPointerException during the preorder traversal.
My node class:
class Node {
int info;
Node left;
Node right;
public Node() {
info = 0;
left = null;
right = null;
}
Node(int x) {
info = x;
left = null;
right = null;
}
}
My Binary Search Tree class:
public class BinarySearchTree {
private Node root;
public BinarySearchTree() {
root = null;
}
private void insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
insertPrivate(node.left, x);
}
else if (x > node.info) {
insertPrivate(node.right, x);
}
}
}
public void insert(int x) {
insertPrivate(root, x);
}
private void preorderPrivate(Node node) {
if(node != null) {
System.out.println(node.info);
preorderPrivate(node.left);
preorderPrivate(node.right);
}
}
public void preorder() {
preorderPrivate(root);
}
public static void main(String[] args) {
BinarySearchTree t = new BinarySearchTree();
t.insert(12);
t.insert(13);
t.preorder();
}
}
The issue is a misunderstanding of Java referencing as seen with this section of code.
private void insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
....
Java references are passed by value into function arguments.
Let me give you an example to clarify.
Node root = new Node(x);
// root == Node(x);
doSomething(root);
// Pass Node(x) into function;
void doSomething(Node node) {
// root == Node(x);
// node == Node(x);
node = new Node(y); // This updates node but not root
// root == Node(x);
// node == Node(y);
}
You are going to have to restructure your program. One way would be to have insertPrivate return a Node and assign that value to root. It is not the most efficient but it will work.
public void insert(int x) {
root = insertPrivate(root, x);
}
private Node insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
node.left = insertPrivate(node.left, x);
}
else if (x > node.info) {
node.right = insertPrivate(node.right, x);
}
}
return node;
}
Change insert(int x) like this:
public void insert(int x) {
if (root == nul)
root = new Node(x);
else
insertPrivate(root, x);
}
Try :
Node left = new Node();
Node right = new Node();
You should somehow return the newly created node and assign it to the left or right node of the parent. Try this:
private Node insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
node.left = insertPrivate(node.left, x);
}
else if (x > node.info) {
node.right = insertPrivate(node.right, x);
}
}
return node;
}
And your public insert function should be:
public void insert(int x) {
root = insertPrivate(root, x);
}
Also preorderPrivate needs a null-checking:
private void preorderPrivate(Node node) {
System.out.println(node.info);
if (node.left != null)
preorderPrivate(node.left);
if (node.right != null)
preorderPrivate(node.right);
}

Why is `root` keep staying null?

I have a very basic binary tree
import java.util.Scanner;
public class ExprTree {
// Data member
private ExprTreeNode root; // reference to root node
private String input;
private Scanner s = new Scanner(System.in);
// Constructor
public ExprTree() {
// root = new ExprTreeNode(key, leftPtr, rightPtr)
}
// Expression tree manipulation methods
public void build() {
System.out.println("Please enter a prefix sequence. avoid using spaces!");
input = s.nextLine();
for(int i = 0; i < input.length(); ++i) {
addToTree(root, input.charAt(i));
}
}
public void expression() {
}
public float evaluate() {
return 0;
}
public void clear() {
}
public void showStructure(ExprTreeNode t) {
if(t == null) // no more
return;
System.out.println(t.getKey() + "-> ");
showStructure(t.getLeft());
showStructure(t.getRight());
}
private void showSubTrees(ExprTreeNode p, int leven) {
}
private void addToTree(ExprTreeNode t, char key) {
if(t == null) { // no more
t = new ExprTreeNode(key, null, null);
return;
}
addToTree(t.getLeft(), key);
addToTree(t.getRight(), key);
}
public ExprTreeNode getRoot() {
return root;
}
public static void main(String[] args) {
ExprTree t = new ExprTree();
t.build();
t.showStructure(t.getRoot());
}
}
And the tree node class:
public class ExprTreeNode {
// Data memebers
private char key;
private ExprTreeNode left,
right;
// Constructor
public ExprTreeNode(char key, ExprTreeNode leftPtr, ExprTreeNode rightPtr) {
this.key = key;
left = leftPtr;
right = rightPtr;
}
public char getKey() {
return key;
}
public void setKey(char key) {
this.key = key;
}
public ExprTreeNode getLeft() {
return left;
}
public void setLeft(ExprTreeNode left) {
this.left = left;
}
public ExprTreeNode getRight() {
return right;
}
public void setRight(ExprTreeNode right) {
this.right = right;
}
}
In this line:
for(int i = 0; i < input.length(); ++i) {
addToTree(root, input.charAt(i));
}
Every time I call addToTree with root, the debugegr shows that root is null,
even though the first time I called addToTree has alloced root, and the debugger shows so.
Why is it keep staying null?
You commented out the line in
public ExprTree() {
// root = new ExprTreeNode(key, leftPtr, rightPtr);
// just use null for both left and right ptr
}
so root is null.
Remember that java is pass by value, so
private void addToTree(ExprTreeNode t, char key) {
if(t == null) { // no more
t = new ExprTreeNode(key, null, null);
return;
}
addToTree(t.getLeft(), key);
addToTree(t.getRight(), key);
}
called with
addToTree(root, input.charAt(i));
t has the same reference as root, ie. null, but isn't a reference to the variable root. So all you are doing is re-assigning a local variable.

Categories