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.
Related
I was about to build a binary tree, I didn't use the Generic because the static method can't invoke it so I planned to use the Object class to replace it. In that way, I could enter any type of value like int or String as I want.
But unfortunately, here it is, it is an error.
I put the code below, and pls help with this. I appreciate it.
import java.util.*;
public class MainFunction {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3};
BinaryTree bt = createBTree(arr,0);//this is where the error is ,(The method createBTree(int[], int) is undefined for the type MainFunction)
}
}
public class BinaryTree
{
private Object val;
private BinaryTree leftBTree;
private BinaryTree rightBTree;
public BinaryTree(Object val)
{
this.val = val;
}
private void clearTree()
{
this.val = null;
this.leftBTree = null;
this.rightBTree = null;
}
public void addRightTree (BinaryTree tree)
{
rightBTree = tree;
}
public void addLeftTree (BinaryTree tree)
{
leftBTree = tree;
}
public void editTree(Object val)
{
this.val = val;
}
public boolean isEmpty(BinaryTree tree)
{
if(tree != null)
return false;
return true;
}
public void deleteTree(BinaryTree tree)
{
tree.clearTree();
if(tree.leftBTree != null)deleteTree(tree.leftBTree);
if(tree.rightBTree != null)deleteTree(tree.rightBTree);
}
public static BinaryTree createBTree(Object[] arr,int index)
{
BinaryTree tree = null;
if(index<arr.length&&arr[index] != null)
{
tree = new BinaryTree(arr[index]);
tree.leftBTree = createBTree(arr,index*2+1);
tree.rightBTree = createBTree(arr,index*2+2);
}
return tree;
}
public void preOrderTraversal(BinaryTree tree)
{
System.out.println(tree.val);
if(tree.leftBTree != null)
preOrderTraversal(tree.leftBTree);
if(tree.rightBTree != null)
preOrderTraversal(tree.rightBTree);
}
public void inOrderTraversal(BinaryTree tree)
{
if(tree.leftBTree != null)
inOrderTraversal(tree.leftBTree);
System.out.println(tree.val);
if(tree.rightBTree != null)
inOrderTraversal(tree.rightBTree);
}
public void postOrderTraversal(BinaryTree tree)
{
if(tree.leftBTree != null)
postOrderTraversal(tree.leftBTree);
if(tree.rightBTree != null)
postOrderTraversal(tree.rightBTree);
System.out.println(tree.val);
}
}
First of all, I didn't get why you can't use generics - with static method, you just make method static, too.
Secondly, int[] is NOT Object[] - because primitives in java are not objects, hence your code is not working.
Here's the fixed code with generics that works (note it uses Integer instead of int):
public class BinaryTree<T> {
private T val;
private BinaryTree<T> leftBTree;
private BinaryTree<T> rightBTree;
public BinaryTree(T val) {
this.val = val;
}
private void clearTree() {
this.val = null;
this.leftBTree = null;
this.rightBTree = null;
}
public void addRightTree(BinaryTree<T> tree) {
rightBTree = tree;
}
public void addLeftTree(BinaryTree<T> tree) {
leftBTree = tree;
}
public void editTree(T val) {
this.val = val;
}
public boolean isEmpty(BinaryTree<T> tree) {
return tree == null;
}
public void deleteTree(BinaryTree<T> tree) {
tree.clearTree();
if (tree.leftBTree != null) deleteTree(tree.leftBTree);
if (tree.rightBTree != null) deleteTree(tree.rightBTree);
}
public static <T> BinaryTree<T> createBTree(T[] arr, int index) {
BinaryTree<T> tree = null;
if (index < arr.length && arr[index] != null) {
tree = new BinaryTree<>(arr[index]);
tree.leftBTree = createBTree(arr, index * 2 + 1);
tree.rightBTree = createBTree(arr, index * 2 + 2);
}
return tree;
}
public void preOrderTraversal(BinaryTree<T> tree) {
System.out.println(tree.val);
if (tree.leftBTree != null)
preOrderTraversal(tree.leftBTree);
if (tree.rightBTree != null)
preOrderTraversal(tree.rightBTree);
}
public void inOrderTraversal(BinaryTree<T> tree) {
if (tree.leftBTree != null)
inOrderTraversal(tree.leftBTree);
System.out.println(tree.val);
if (tree.rightBTree != null)
inOrderTraversal(tree.rightBTree);
}
public void postOrderTraversal(BinaryTree<T> tree) {
if (tree.leftBTree != null)
postOrderTraversal(tree.leftBTree);
if (tree.rightBTree != null)
postOrderTraversal(tree.rightBTree);
System.out.println(tree.val);
}
public static void main(String[] args) {
Integer[] arr = new Integer[]{1, 2, 3};
BinaryTree<Integer> bt = createBTree(arr, 0);
}
}
I have no idea what direction to take with this - I'm trying to parse an expression "(4 + 3)", and build a Tree from it. However, In my EvalExp method I have no idea what to do from here. The ordering for the expression should be value/operator/value/operator so I've put in 2 stacks, to identify either. Any ideas what I should do next?
public class Tree {
class ExprTreeNode {
ExprTreeNode left, right;
boolean isLeaf;
int value;
char op;
public ExprTreeNode(int value) {
this.value = value;
this.op = op;
this.left = null;
this.right = null;
}
}
private Stack opStk = new Stack();
private Stack valStk = new Stack();
private ExprTreeNode root;
public Tree(String s) {
root = (ExprTreeNode) EvalExp(s);
}
public Object EvalExp(String str) {
Scanner s = null;
try {
s = new Scanner(str);
while (s.hasNext()) {
// push to val stk
if (s.hasNextInt()) {
valStk.push(s.next());
} else {
opStk.push(s.next());
}
}
} finally {
if (s != null) {
s.close();
}
}
//return the root node
return valStk.peek();
}
Why not use a recursive descent parser instead of explicit stacks? Should be something along the lines of
static ExprTreeNode parseExpr(Scanner s) {
ExprTreeNode left = parsePrimary(s);
if (s.hasNext("\\+")) {
s.next("\\+");
ExprTreeNode right = parseExpr(s);
return new ExprTreeNode('+', left, right);
}
return left;
}
public static ExprTreeNode parsePrimary(Scanner s) {
return new ExprTreeNode(parseNextInt());
}
My binary tree looks pretty close to my class materials, but when I print to the console or check for contains(), any adds I'm doing aren't registered.
I don't have a great understanding of static and the debugger is giving me a hint about making a static reference to non-static variable overallRoot, but everything compiles without error or warning in eclipse.
public class BSTSimpleSet<E extends Comparable<E>> implements SimpleSet<E> {
private GTNode<E> overallRoot;
private int size;
public static void main(String[] args) {
BSTSimpleSet<Integer> main = new BSTSimpleSet<Integer>(2);
main.toString();
main.add(3);
main.toString();
main.add(4);
main.toString();
main.add(5);
main.toString();
System.out.print(main.contains(3));
}
public BSTSimpleSet() {
size = 0;
}
public BSTSimpleSet(E input) {
overallRoot = new GTNode<E>(input);
size = 1;
}
public boolean add(E e) {
return add(e, overallRoot);
}
private boolean add(E e, GTNode<E> root) {
if (root == null) {
root = new GTNode<E>(e);
size++;
return true;
} else {
int compare = e.compareTo(root.data);
if (compare == 0) {
return false;
} else if (compare < 0) {
return add(e, root.left);
} else {
return add(e, root.right);
}
}
}
public void clear() {
overallRoot = null;
}
public boolean contains(E e) {
return contains(e, overallRoot);
}
private boolean contains(E e, GTNode<E> root) {
if (root == null) {
return false;
} else {
int compare = e.compareTo(root.data);
if (compare == 0) {
return true;
} else if (compare < 0) {
return contains(e, root.left);
} else {
return contains(e, root.right);
}
}
}
public boolean isEmpty() {
if (overallRoot == null) {
return false;
} else {
return true;
}
}
public int size() {
return size;
}
public String toString() {
this.toString(overallRoot, 0);
return null;
}
private void toString(GTNode<E> root, int level) {
if (root != null) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println(root.data);
toString(root.left, level + 1);
toString(root.right, level + 1);
} else {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println("_");
}
}
private static class GTNode<E extends Comparable<E>> {
public E data;
public GTNode<E> left;
public GTNode<E> right;
public GTNode(E input) {
this(input, null, null);
}
public GTNode(E input, GTNode<E> lNode, GTNode<E> rNode) {
data = input;
left = lNode;
right = rNode;
}
}
}
This code does absolutely nothing.
private boolean add(E e, GTNode<E> root) {
if (root == null) {
root = new GTNode<E>(e);
size++;
return true;
}
...
Java passes in the Object Reference to a method. If you change the Reference, that will not
be propagated back to the calling method. If you change what the Reference refers to
that will be propagated back.
eg
// arrays behave the same way so using them to illustrate.
public void callMethods(){
int[] array = new int[1];
array[0] = 0;
doesNotChange(array);
System.out.println(array[0]);// will print 0
doesAChange(array);
System.out.println(array[0]);// will print 1
}
public void doesNotChange(int[] myArray){
myArray = new int[1];
myArray[0] = 1;
}
public void doesAChange(int[] myArray){
myArray[0] = 1;
}
To avoid these sorts of things I recommend always setting method parameters final.
The GTNode class shouldn't be static. Static classes are classes with only static methods, which means they don't have to be instantiated. The prototypical example of this is the java.lang.Math class: You don't need to call something like Math m = new Math(); m.cos(); to get the cosine, you just call Math.cos(). Since you're creating multiple instances of the GTNode class, make it non-static and you should be good.
Im trying to test a java generic class that i wrote, this is my test
public class BSTTest
{
public void testInsert()
{
int height;
BST<int> myTree = new BST<int>();
myTree.insert(1);
}
}
but when i compile i get the error of unexpected type, it says if found an int but requires a reference on the line of BST myTree = new BST(); what does that mean?
below are my Binary search tree and node class for reference
public class BST<E extends Comparable<E>>
{
public Node<E> root;
public BST()
{
root = null;
}
//insert delete find height
public void find(E s, Node<E> n)
{
//empty tree, root is null
if(n == null)
{
System.out.println("Item not present.");
}
//n is the node where s is, return n
else if(n.getData().equals(s))
{
System.out.println("Item present");
}
//s is greater than n, look for s on the right subtree
else if(s.compareTo(n.getData()) > 0)
{
find(s, n.getRight());
}
//s is less than n, look for s on the left subtree
else
{
find(s, n.getLeft());
}
}
public int height()
{
int count;
return count = height(root);
}
private int height(Node<E> n)
{
int ct = 0;
if(n == null)
{
}
else
{
int left = height(n.getLeft());
int right = height(n.getRight());
ct = Math.max(left, right) + 1;
}
return ct;
}
public void insert(E s)
{
root = insert(s, root);
}
private Node<E> insert(E s, Node<E> T)
{
//easiest case, empty tree, create new tree
if(T == null)
{
T = new Node<E>(s,null,null);
}
//easiest case, found s
else if(s.compareTo(T.getData()) == 0)
{
System.out.println("Item already present.");
}
//s is greater than T, insert on right subtree
else if(s.compareTo(T.getData()) > 0)
{
T.setRight(insert(s, T.getRight()));
}
//s is less than T, insert on left subtree
else
{
T.setLeft(insert(s,T.getLeft()));
}
return T;
}
public void delete(E d)
{
}
}
and my node class
public class Node<E>
{
private E data;
private Node<E> left;
private Node<E> right;
private Node<E> parent;
public Node(E d, Node<E> r, Node<E> l)
{
data = d;
left = l;
right = r;
}
public void setData(E d)
{
data = d;
}
public E getData()
{
return data;
}
public Node<E> getRight()
{
return right;
}
public void setRight(Node<E> nd)
{
right = nd;
}
public Node<E> getLeft()
{
return left;
}
public void setLeft(Node<E> nd)
{
left = nd;
}
public Node<E> getParent()
{
return parent;
}
public void setParent(Node<E> nd)
{
parent = nd;
}
}
Can you try Integer instead of int?
Generic type takes only Classes (Object types) and not the primite data type
It should be
BST<Integer> myTree = new BST<Integer>();
Java generics are only for Object types. Since, int is a primitive type you cannot use it. Instead use BST<Integer>
You can't use a primitive type like int as a parameter to a generic class in Java. It has to be a class type, such as Integer.
Im new to generics and i have to implement a binary search tree using generics. I did that but now im wondering how do i test the code that i wrote? Do i just make another class and start using the methods of the bst?
any help would be appreciated. below is my code just to clarify.
public class BST<E extends Comparable<E>>
{
public Node<E> root;
public BST()
{
root = null;
}
//insert delete find height
public void find(E s, Node<E> n)
{
//empty tree, root is null
if(n == null)
{
System.out.println("Item not present.");
}
//n is the node where s is, return n
else if(n.getData().equals(s))
{
System.out.println("Item present");
}
//s is greater than n, look for s on the right subtree
else if(s.compareTo(n.getData()) > 0)
{
find(s, n.getRight());
}
//s is less than n, look for s on the left subtree
else
{
find(s, n.getLeft());
}
}
public int height()
{
int count;
return count = height(root);
}
private int height(Node<E> n)
{
int ct = 0;
if(n == null)
{
}
else
{
int left = height(n.getLeft());
int right = height(n.getRight());
ct = Math.max(left, right) + 1;
}
return ct;
}
public void insert(E s)
{
root = insert(s, root);
}
private Node<E> insert(E s, Node<E> T)
{
//easiest case, empty tree, create new tree
if(T == null)
{
T = new Node<E>(s,null,null);
}
//easiest case, found s
else if(s.compareTo(T.getData()) == 0)
{
System.out.println("Item already present.");
}
//s is greater than T, insert on right subtree
else if(s.compareTo(T.getData()) > 0)
{
T.setRight(insert(s, T.getRight()));
}
//s is less than T, insert on left subtree
else
{
T.setLeft(insert(s,T.getLeft()));
}
return T;
}
public void delete(E d)
{
}
}
and my node class
public class Node<E>
{
private E data;
private Node<E> left;
private Node<E> right;
private Node<E> parent;
public Node(E d, Node<E> r, Node<E> l)
{
data = d;
left = l;
right = r;
}
public void setData(E d)
{
data = d;
}
public E getData()
{
return data;
}
public Node<E> getRight()
{
return right;
}
public void setRight(Node<E> nd)
{
right = nd;
}
public Node<E> getLeft()
{
return left;
}
public void setLeft(Node<E> nd)
{
left = nd;
}
public Node<E> getParent()
{
return parent;
}
public void setParent(Node<E> nd)
{
parent = nd;
}
}
Im trying to follow what you said, this is my test class
public class BSTTest
{
public void testInsert()
{
int height;
BST myTree = new BST();
myTree.insert(1);
}
}
but when i compile i get the error of unexpected type, it says if found an int but requires a reference on the line of BST myTree = new BST(); what does that mean?
Yes, make a class called BSTTest and create methods to test each of the public methods in BST.
If you use JUnit, you can use annotations and a standard naming convention
public class BSTTest {
#Test
public void testInsert() {
BST<String> bst = new BST<String>();
String s = "hello";
bst.insert(s);
AssertTrue("I should get back what I put in!", bst.find(s));
}
#Test
public void testDelete() {
// etc...
}
}
Then, you can run this 'Unit Test' in your java IDE (such as IntelliJ IDEA) or, if you have it set up, via maven: mvn test.
Also, I think your find() method could return boolean?
good luck!