In the code below, the nodes of a postorder tree traversal is always printed
I m wondering if there is a way to store these nodes in the postorder sequence in an array
Do i have to do the traversal in a iterative way?
public static void postOrder(TreeNode root) {
if (root != null) {
postOrder(root.left);
postOrder(root.right);
System.out.print(root.item + " ");
} else {
return;
}
}
Just pass a List along with that method. Untested pseudo-ish code:
class Tree {
private TreeNode root;
// ...
public List<TreeNode> postOrder() {
List<TreeNode> nodes = new ArrayList<TreeNode>();
fillList(root, nodes);
return nodes;
}
private void fillList(TreeNode node, List<TreeNode> nodeList) { // private!
if(node != null) {
fillList(node.left, nodeList);
fillList(node.right, nodeList);
nodeList.add(node);
}
}
}
I would recommend a list instead of an array. That way you don't need to worry about the size of your tree. (Using an array you should first count the nodes in your tree, which would practically require another full traversal.) Storing the tree nodes themselves is achieved by this method:
public static void postOrder(TreeNode root, List<TreeNode> list) {
if (root != null) {
postOrder(root.left, list);
postOrder(root.right, list);
list.add(root);
} else {
return;
}
}
If you want to store only the items (supposing their type is TreeNodeItem):
public static void postOrder(TreeNode root, List<TreeNodeItem> list) {
if (root != null) {
postOrder(root.left, list);
postOrder(root.right, list);
list.add(root.item);
} else {
return;
}
}
The need to create the final array is ugly, but here's a mock-up, including a potential definition of type TreeNode:
final class TreeAccumulator
{
public static final class TreeNode<T>
{
public TreeNode(T item,
TreeNode<? extends T> left,
TreeNode<? extends T> right) {
this.item = item;
this.left = left;
this.right = right;
}
public final T item;
public final TreeNode<? extends T> left;
public final TreeNode<? extends T> right;
}
public static <T, C extends Collection<T>>
C postOrder(TreeNode<? extends T> root, C acc)
{
if (null == root)
return acc;
final C result = postOrder(root.right,
postOrder(root.left, acc));
result.add(root.item);
return result;
}
#SuppressWarnings({"unchecked"})
public static <T> T[] postOrder(TreeNode<? extends T> root,
Class<T> c)
{
final Collection<T> acc = postOrder(root, new LinkedList<T>());
return acc.toArray((T[])Array.newInstance(c, acc.size()));
}
}
If you knew more about the potential size of the tree ahead of time, you could collect into a pre-allocated ArrayList -- or even a primitive array -- more easily.
Related
I am getting this mystical error:
The operator > is undefined for the argument type(s)
java.lang.Comparable, java.lang.Comparable
What the heck?
(here's the code)
public class BST<T extends Comparable<T>> {
public static class Node<P extends Comparable<P>> {
P val;
Node<P> left;
Node<P> right;
public Node() {
}
public Node(P val) {
this.val = val;
}
}
Node<T> root;
private void addValHelper(Node root, Node newNode) {
if (root.val > newNode.val) { // <-- ERROR IS HERE
if (root.left == null) {
root.left = newNode;
} else {
addValHelper(root.left, newNode);
}
} else {
if (root.right == null) {
root.right = newNode;
} else {
addValHelper(root.right, newNode);
}
}
}
}
Java doesn't have operator overloading. You can't compare Comparable types with >. You need to use root.val.compareTo(newNode.val) instead.
As an aside:
Comparable is an interface, not a class
You don't need to specify <P extends Comparable<P>>
It might make more sense to move the addValHelper code into the Node class itself
It might make sense for Node to implement Comparable.
This way, your code feels a lot more idiomatic and you don't expose fields of Node to BST.
public class BST<T implements Comparable<T>> {
private final Node<T> root;
/** Presumably this is run when a value is added.. */
private void addValueHelper(Node rootNode, Node newNode) {
rootNode.attachChild(newNode);
}
public static class Node implements Comparable<T> {
private final T val;
private Node left;
private Node right;
public Node(T val) {
this.val = val;
}
public int compareTo(Node other) {
return this.val.compareTo(other.val);
}
/**
* Takes the given node and compares it with the current node.
* If the current node is greater than the given node, the given node is placed to the left.
* Otherwise it is placed to the right.
*/
protected void attachChild(Node newNode) {
if (this.compareTo(newNode) == 1) {
if (this.left == null) {
this.left = newNode;
return;
}
this.left.attachChild(newNode);
return;
}
if (this.right == null) {
this.right = newNode;
return;
}
this.right.attachChild(newNode);
}
}
}
public class Node {
private int data;
public int getData() {
return data;
}
private Node left;
private Node right;
public Node(int d, Node l, Node r) {
data = d;
left = l;
right = r;
}
// Deep copy constructor
public Node(Node o) {
if (o == null) return;
this.data = o.data;
if (o.left != null) this.left = new Node(o.left);
if (o.right != null) this.right = new Node(o.right);
}
public List<Integer> toList() {
// Recursive code here that returns an ordered list of the nodes
}
The full class is here: https://pastebin.com/nHwXMVrd
What recursive solution could I use to return an ordered ArrayList of the Integers inside the Node? I've tried a lot of things but I have been having difficulties to find a recursive solution.
Given that you have a bst you can make an inorder traversal on in, this will give you all the elements in increasing order (sorted), an example of how it's done:
public List<Integer> toList() {
return createOrderedList(this);
}
private List<Integer> createOrderedList(Node root) {
if(root == null) {
return new ArrayList<>();
}
List<Integer> list = new ArrayList<>();
list.addAll(createOrderedList(root.left));
list.add(root.data);
list.addAll(createOrderedList(root.right));
return list;
}
I am not profficent in Java but this would be the general idea of doing it:
public List<Integer> toList()
{
List<Integer> newList = new List<Integer>();
newList.add(this.data);
if(left != null)
newList.addAll(left.toList());
if(right != null)
newList.addAll(right.toList());
return newList;
}
I am trying to print a binary tree by BFS.
my implementation is with a PriorityQueue.
in the beginning i insert root into PriorityQueue.
then in loop, i pull a node from PriorityQueue, print it, and insert his childs(if thay are not null) into PriorityQueue.
why when inserting the second node, i get this exception:
Exception in thread "main" java.lang.ClassCastException: Node cannot be cast to java.lang.Comparable
this is my code:
class main:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Tree tree = new Tree();
}
}
class Node:
public class Node {
public Node(){}
public Node(int num)
{
value = num;
}
private int value;
private Node left;
private Node right;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
class tree:
public class Tree {
private Node root;
public Tree()
{
root = new Node(5);
Node node2 = new Node(2);
Node node10 = new Node(10);
Node node8 = new Node(8);
Node node6 = new Node(6);
Node node15 = new Node(15);
root.setRight(node10);
root.setLeft(node2);
node10.setRight(node15);
node10.setLeft(node8);
node8.setLeft(node6);
printToWidth(root);
}
public void printToWidth(Node node)
{
PriorityQueue<Node> queue = new PriorityQueue<Node>();
queue.add(node);
while( !(queue.isEmpty()))
{
Node n = queue.poll();
System.out.println(n.getValue());
if (n.getLeft() != null)
queue.add(n.getLeft());
if (n.getRight() != null)
queue.add(n.getRight());
}
System.out.println("end printToWidth");
}
}
You've got two options:
Make Node implement Comparable<Node>, so that the elements can be inserted according to their natural ordering. This is likely the easier of the two.
public int compareTo(Node other) {
return value - other.getValue();
}
Use a custom Comparator<Node> and supply a compare method there, with an initial capacity.
PriorityQueue<Node> queue = new PriorityQueue<Node>(10, new Comparator<Node>() {
public int compare(Node left, Node right) {
return left.getValue() - other.getValue();
}
});
The exception is telling you, make Node implement Comparable<Node>.
You can insert the first node because it has nothing to compare to, so the comparison is not needed.
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!