Parsing a String to construct a Tree in Java - java

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());
}

Related

Changing BST from working with int to strings

I am trying to build a simple BST that works with strings right now I am just trying to get an insert method to will add tryings. Right now I have it were it will insert int any thoughts on how to change this to take strings
UPDATED:
I have some things working but now I can not get my tree to print out like I want it to?
public class BinaryStringTree {
private String data;
private BinaryStringTree left;
private BinaryStringTree right;
public BinaryStringTree() {
this.data = null;
this.left = null;
this.right = null;
}
public BinaryStringTree(String data) {
this.data = data;
this.left = null;
this.right = null;
}
public void addNode(String data) {
if (this.data == null) {
this.data = data;
} else {
if (this.data.compareTo(data) < 0) {
if (this.left != null) {
this.left.addNode(data);
} else {
this.left = new BinaryStringTree(data);
}
} else {
if (this.right != null) {
this.right.addNode(data);
} else {
this.right = new BinaryStringTree(data);
}
}
}
}
public void traversePreOrder() {
System.out.println(this.data);
if (this.left != null) {
this.left.traversePreOrder();
}
if (this.right != null) {
this.right.traversePreOrder();
}
}
public static void main(String args []){
BinaryStringTree bstree = new BinaryStringTree();
bstree.addNode("Copperfield");
bstree.addNode("Houdini");
bstree.addNode("Cardini");
bstree.addNode("Blackstone");
bstree.addNode("Dante");
bstree.addNode("Malini");
bstree.addNode("Vernon");
bstree.addNode("Liepzig");
bstree.addNode("Wild");
bstree.addNode("Farquar");
bstree.addNode("Thurston");
bstree.addNode("Page");
bstree.addNode("Dedi");
bstree.addNode("Hofzinser");
bstree.addNode("Farmer");
bstree.addNode("Burton");
bstree.addNode("Lorayne");
bstree.addNode("Devant");
bstree.addNode("Maskelyne");
bstree.addNode("Blaney");
bstree.addNode("Ortiz");
bstree.addNode("Munoz");
bstree.addNode("Bertram");
bstree.addNode("Daniels");
bstree.addNode("Beam");
bstree.addNode("Regal");
bstree.addNode("Ammar");
bstree.addNode("Nicola");
bstree.addNode("Fulves");
bstree.addNode("Ganson");
bstree.addNode("Close");
bstree.addNode("Lumiere");
}
}
You can make your BST class generic, which would allow it to take any type for which an ordering is defined.
Instead of using < for comparison, make your class take a type parameter T that implements Comparable<T>, and use key.compareTo(insNode.getKey()) < 0.
If you don't want a generic class, simply replace your int values with Strings, and replace the < operator with compareTo (since String implements Comparable<String>).

LinkedList addToTail() not working

I can't figure why the addition to the tail of this LinkedList class is not working and is simply ignored in the output.
Here's a simple Node class:
public class IntNode {
private int val;
private IntNode next;
public IntNode() {
this.val = 0;
IntNode next = null;
}
public IntNode(int val) {
this.val = val;
this.next = null;
}
public IntNode next() {
return this.next;
}
public int getVal() {
return this.val;
}
public void setNextNode(int val) {
this.next = new IntNode(val);
}
public void setNextNode(IntNode a)
{
this.next = new IntNode(a.getVal());
}
public void setVal(int val) {
this.val = val;
}
public String toString() {
StringBuffer buff = new StringBuffer();
return toString(this, buff);
}
private String toString(IntNode node, StringBuffer buff) {
if (node == null) {
return buff.toString();
}
buff.append(node.val);
if (node.next != null) {
buff.append(", ");
} else {
buff.append(".");
}
return toString(node.next(), buff);
}
}
And here's the linked list for it:
public class LinkedList {
private IntNode header;
private IntNode trailer;
private int listSize;
public LinkedList()
{
this.header = null;
this.trailer = null;
this.listSize = 0;
}
public LinkedList(IntNode a, IntNode b)
{
this.header = a;
this.trailer = b;
this.header.setNextNode(this.trailer);
this.listSize = 2;
}
public void addNode(IntNode a)
{
this.trailer.setNextNode(a.getVal());
this.trailer = this.trailer.next();
this.listSize++;
}
public String toString()
{
return this.header.toString();
}
public static void main(String args[])
{
LinkedList lst = new LinkedList(new IntNode(1), new IntNode(2));
lst.addNode(new IntNode(3));
lst.addNode(new IntNode(4));
System.out.println(lst.toString());
}
}
The output of the main method is: 1, 2.
Why is the addition method not working?
In your constructor with two IntNodes, your header is not pointing to your trailer. Instead it points to a new IntNode(trailer.val). You should change
public void setNextNode(IntNode a)
{
this.next = a;
}
Your problem is that the LinkedList constructor sets header to a and trailer to b, but then calls header.setNextNode(this.trailer);
IntNode's method setNextNode() method discards the node that it is passed and instead creates a node with the same value as the one that it had passed in.
This means that at the end of your LinkedList constructor you have the header assigned to a which has a next node value of something other than b that has the same value as b, while trailer is set to b.
You should change your setNextNode() method to not discard the node it's handed in, as follows:
public void setNextNode(IntNode a) {
this.next = a;
}
In the constructor of the LinkedList class you have the code this.header.setNextNode(this.trailer);. This will not set the next node of the head to the trailer, but set the next node of the head to another node with the value of the trailer. When the trailer's next node is set, the head is not affected.

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.

Java Generic Class Test

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.

Java Generics Test class

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!

Categories