I've been working on this program for a few days now and I've implemented a few of the primary methods in my BinarySearchTree class such as insert and delete. Insert seemed to be working fine, but once I try to delete I kept getting errors. So after playing around with the code I wanted to test my compareTo methods. I created two new nodes and tried to compare them and I get this error:
Exception in thread "main" java.lang.ClassCastException: TreeNode cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at TreeNode.compareTo(TreeNode.java:16)
at BinarySearchTree.myComparision(BinarySearchTree.java:177)
at main.main(main.java:14)
Here is my class for creating the nodes:
public class TreeNode<T> implements Comparable
{
protected TreeNode<T> left, right;
protected Object element;
public TreeNode(Object obj)
{
element=obj;
left=null;
right=null;
}
public int compareTo(Object node)
{
return ((Comparable) this.element).compareTo(node);
}
}
Am I doing the compareTo method all wrong? I would like to create trees that can handle integers and strings (seperatly of course)
To be sure that the element indeed is a comparable object, and avoid all the casts, you could do something like this:
public class TreeNode<T extends Comparable<? super T>>
implements Comparable<TreeNode<T>> {
protected TreeNode<T> left, right;
protected T element;
public TreeNode(T obj) {
element = obj;
left = null;
right = null;
}
#Override
public int compareTo(TreeNode<T> node) {
return element.compareTo(node.element);
}
}
For an usage example:
TreeNode<Integer> node1 = new TreeNode<Integer>(2);
TreeNode<Integer> node2 = new TreeNode<Integer>(3);
System.out.println(node1.compareTo(node2));
The above snippet prints -1 on the console.
compareTo method is applied against TreeNode (passed as node parameter), while you compare it with this.element, which is an Object contained in the TreeNode. Simply change to:
return ((Comparable) this.element).compareTo(node.getElement());
assuming you have getElement method.
Try
public <T> int compareTo(Object node)
{
return ((Comparable) this.element).compareTo( ( TreeNode<T> ) node ).element);
}
Related
I'm writing this in java.
I've got a BinaryTree Class. It has functions that use the Node class.
I've written a subclass of Binary Tree (TraversalTree) and I've got a subclass of the Node class (OrderNode).
How do I get the TraversalTree functions that inherit from BinaryTree to use the subclass OrderNode??
public class BinaryTree {
public Node root; // starting node of the tree
public Node getRoot() {
return root;
}
}
public class Node {
private int value;
private Node left, right, parent;
//constructor
public Node(int value) {
this.value = value; // data value to be stored in node
left = null; // left child
right = null; // right child
parent = null; // parent node
}
}
So here is the subclass OrderNode
public class OrderNode extends Node {
public int preOrder,postOrder, inOrder;
public OrderNode(int value) {
super(value);
}
}
And then in this subclass of BinaryTree, TraversalTree. I want it to have the subclass OrderNode replace all the Node calls in the BinaryTree functions.
public class TraversalTree extends BinaryTree {
}
I've tried to search this a bunch but I'm hitting a wall. Perhaps I haven't been able to find the right search terms. But either way I can't seem to find any info on this.
You can use super to access the super variables and assign sub class object in super class reference variables.
class TraversalTree extends BinaryTree {
public TraversalTree(OtherNode otherNode){
super.node=otherNode;
}
public OtherNode getRoot(){
return (OtherNode)super.getRoot();
}
}
This should replace all node with otherNode.
How do you insert items into a binary tree in java so that they are in order? I want to use random values and sort them from smallest to largest then insert them into a binary tree in this order:
1
2 3
4 5 6 7
8 9
When you say 'in order' you need to clarify, do you mean in sorted order or do you mean insertion order, etc.
There are lots of resources available on inserting into binary trees or the difference between to types of binary trees, or how to print a binary tree diagram, that I suspect this is a duplicate.
What is different about your example? Having '1' as the root node means you must not have a rebalancing tree since both '2' and '3' are larger than the value for your root node. Your insert rule seems inconsistent since if '1' is the first node inserted then all other values will cascade to the right branch of the tree unless you use a different rule for the root then at the other levels which would be a pain to code.
Something like this?:
public class BinaryTree {
private List<Integer> list = new ArrayList<Integer>();
public class BinaryTreeNode {
private int p;
public BinaryTreeNode(int p) {
this.p = p;
}
private BinaryTreeNode getChild(int childP){
BinaryTreeNode result= null;
if (childP < list.size()){
result = new BinaryTreeNode(childP);
}
return result;
}
public BinaryTreeNode getLeft(){
return getChild(p*2+1);
}
public BinaryTreeNode getRight(){
return getChild(p*2+2);
}
public int getValue(){
return list.get(p);
}
}
public void add(int item){
list.add(item);
}
public BinaryTreeNode getRoot(){
BinaryTreeNode result = null;
if (!list.isEmpty()){
result = new BinaryTreeNode(0);
}
return result;
}
}
In Naftalin, Walder Java Collections and Generics I've faced with this implementation that I love best:
public interface TreeVisitor<E, R> {
public R visit(E leaf);
public R visit(E value, Tree<E> left, Tree<E> right);
}
public abstract class Tree<E> {
public abstract <R> R accept(TreeVisitor<E, R> visitor);
public static <E> Tree<E> leaf(final E leaf) {
return new Tree<E>() {
#Override
public <R> R accept(TreeVisitor<E, R> visitor) {
return visitor.visit(leaf);
}
};
}
public static <E> Tree<E> branch(final E value, final Tree<E> left, final Tree<E> right){
return new Tree<E>(){
#Override
public <R> R accept(TreeVisitor<E, R> visitor) {
return visitor.visit(value, left, right);
}
};
}
}
Now you can add any operation you want and create your tree as follows:
Tree<Integer> t = Tree.branch(1,
Tree.branch(2,
Tree.branch(4, Tree.leaf(8), Tree.leaf(9)), Tree.leaf(5)),
Tree.branch(3, Tree.leaf(6), Tree.leaf(7));
I found the answer that I needed from this one.
Create a Complete Binary Tree using Linked Lists w/o comparing node values
Some of the other things I was pointed to, either weren't quite what I wanted, or didn't work past like 8 or so values.
I have the following design:
I have an Abstract class Instance,
I have a class Library that extends Instance and
I have a class File that also extends Instance
I've created my own linked list implementation and it's defined as follows:
public class List<T extends Instance> implements Iterable {
//some other code here
public Iterator iterator(){
return new ListIterator(this);
}
now I've created a class
public class ListIterator<T extends Instance> implements Iterator<T> {
private List thisList;
private Node current;
public ListIterator(List l){
thisList=l;
current=thisList.head.next;
}
#Override
public boolean hasNext() {
if(current==null)
return false;
return false;
}
#Override
public T next() {
Node temp=current;
current=current.next;
return temp.data;
}
}
Where Node is
public class Node<T extends Instance> {
public Node<T> next;
public Node<T> prev;
public T data;
public Node(T data,Node prev, Node next){
this.data=data;
this.prev=prev;
this.next=next;
}
}
so my problem is as follows: the line return temp.data rises an error:
Type mismatch - cannot convert from Instance to T.
What is wrong with this code?
I'd say that Node.data is a reference to an Instance object? If that is the case, the compiler can't automatically change an Instance to a T, because even though T is an Instance object (T extends Instance), any given Instance might not be a T.
The Java Generics tutorial explains it: http://docs.oracle.com/javase/tutorial/extra/generics/subtype.html
Also, in your List<T> class, you should be specifying Iterator and ListIterator as generic using Iterator<T> and ListIterator<T>, or else the compiler won't be able to handle the generics properly. Your Node reference also needs to be generic: Node<T>
Hence you should be using
private Node<T> current;
and
public T next() {
Node<T> temp=current;
current=current.next;
return temp.data;
}
The compiler will usually warn you when you're using a raw type for a generic class.
Did no one notice the bug:
public boolean hasNext() {
if(current==null)
return false;
return false;
}
This is an invariant. Unless I am missing something, the iterator will very quickly return 0 elements!
I am implementing a sorted list using linked lists. My node class looks like this
public class Node<E>{
E elem;
Node<E> next, previous;
}
In the sorted list class I have the add method, where I need to compare generic objects based on their implementation of compareTo() methods, but I get this syntax error
"The method compareTo(E) is undefined for type E". I have tried implemnting the compareTo method in Node, but then I can't call any of object's methods, because E is generic type.
Here is the non-finished body of add(E elem) method.
public void add(E elem)
{
Node<E> temp = new Node<E>();
temp.elem = elem;
if( isEmpty() ) {
temp.next = head;
head.previous = temp;
head = temp;
counter++;
}else{
for(Node<E> cur = head; cur.next != null ; cur= cur.next) {
**if(temp.elem.comparTo(cur.elem)) {**
//do the sort;
}/*else{
cur.previous = temp;
}*/
}
//else insert at the end
}
}
Here is one of the object implemnting compareTo method
public class Patient implements Comparable<Patient>{
public int compareTo(Patient that)
{
return (this.getPriority() <= that.getPriority() ? 1 : 0 );
}
}
Bound E to Comparable:
public class Node<E extends Comparable<E>>{
E elem;
Node<E> next, previous;
}
It will compile now.
If you want the elements stored in your nodes to be comparable, you can state this using generics:
public class Node<E extends Comparable<E>> {
E elem;
Node<E> next, previous;
}
this way it is sure, that every E implements the Comparable interface, so you can safely call the compareTo method.
It seems that your generic E must be E extends Comparable<E>. This way you will get the access to the compareTo(E other) method. However, you will be unable to add elements that are not implementing this interface.
Try
public class Node<E extends Comparable<E>>{
E elem;
Node<E> next, previous;
}
I need to write a tree class in Java where each level has a unique object type. The way it is written below does not take advantage of generics and causes alot of duplicate code. Is there a way to write this with Generics ?
public class NodeB {
private String nodeValue;
//private List<NodeB> childNodes;
// constructors
// getters/setters
}
public class NodeA {
private String value;
private List<NodeB> childNodes;
// constructors
// getters/setters
}
public class Tree {
private String value;
private List<NodeA> childNodes;
// constructors
// tree methods
}
This is simplistic implementation, but enough to give general idea:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class GenericNode {
public static abstract class AbstractNode<V, N> {
private V value;
private List<N> children;
public AbstractNode(V value, N... children) {
this.value = value;
this.children = children != null ? Arrays.asList(children)
: Collections.<N> emptyList();
}
public V getValue() {
return value;
}
public List<N> getChildren() {
return children;
}
public int getNumberOfChildren() {
return children.size();
}
#Override
public String toString() {
return value.toString() + "->" + children.toString();
}
}
// leaf node type, ignore type of children
public static class NodeB extends AbstractNode<String, Object> {
public NodeB(String value, Object... nodes) {
super(value, nodes);
}
}
// example of typical node in the mid of tree
public static class NodeA extends AbstractNode<String, NodeB> {
public NodeA(String value, NodeB... nodes) {
super(value, nodes);
}
}
// top level node type
public static class Tree extends AbstractNode<String, NodeA> {
public Tree(String value, NodeA... nodes) {
super(value, nodes);
}
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public static <V, N extends AbstractNode> int getNodeCount(
AbstractNode<V, N> node) {
int nodeCount = node.getChildren().size();
for (N child : node.getChildren()) {
nodeCount += getNodeCount(child);
}
return nodeCount;
}
public static void main(String[] args) {
NodeB nodeB1 = new NodeB("Leaf node 1");
NodeB nodeB2 = new NodeB("Leaf node 2");
NodeA nodeA = new NodeA("Node with children", nodeB1, nodeB2);
NodeA emptyNodeA = new NodeA("Empty node");
Tree tree = new Tree("Tree", nodeA, emptyNodeA);
System.out.println(tree);
System.out.println(1 + getNodeCount(tree));
}
}
You could make N and V types implement specific interfaces so it will be possible to call some common operations on values and/or children.
EDIT: updated implementation with recursive method for node count retrieval
All you need is a Pair<A, B>. Example of trees:
Pair<A, Pair<B, C>>
Pair<Pair<A, B>, Pair<C, D>>
Pair<Pair<Pair<A, B>, Pair<C, D>>, Pair<Pair<E, F>, Pair<G, H>>
ps: don't do this. :)
This is an ideal spot for everything inheriting from "Node", but even that is unnecessary.\
What you probably want is a single generic "Node" object that contains references to your different classes (use composition before inheritance).
At that point, each of your different classes probably has something that can be done to them (otherwise why are they all in the same data structure?) Have them implement a common interface with this common functionality. The node class can delegate to this interface, or some other class can extract the class by this interface and act on it.
This would be better than trying to force something to also BE a node--do one simple thing and do it well.
--edit--
I can't really add an example that is relevant to you because you didn't post anything about your scenario.
But let's say that you have these different classes A, B * C. First of all are they related AT ALL aside from all being children of Object? Let's say they all implement interface "Iface". (If not, you can just replace Iface with "Object", but this really implies a bad design.)
Anyway, your "Node" object is just one object--
public class Node {
private List<node> children;
private Iface myObject;
... setters, getters, tree implementation, tree navigation, related garbage...
}
Now this is enough to create your tree. One thing that you might be able to do to make things smoother, have "Node implements Iface" and delegate any calls to it's object. For instance, if Iface contains an eat(Food foodtype) method, your node could implement Iface and have a method:
public void eat(Food foodtype) {
myObject.eat(foodtype);
}
This would make the "Node" class act as though it was the class it contained.
By the way--another relatively good idea at this point would be to make myObject "private final" and ensure it is not null in the constructor. That way you would always know it was set and none of your delegated members would have to do null checks.
I don't think generics are going to help you much in this case. Instead of having a different class for each level in the tree. What about one node class that has children and store a different class on each level. That should help eliminate a lot of the duplication.
I'm fairly new to Java, so this might have issues I'm not aware of, but it seems to work on a simple level at least.
Define your main Node class - this one will be the root of the tree.
public class NodeA {
private String _value;
private ArrayList<NodeA> _children;
private int _depth;
public NodeA (String value, int depth) {
_value = value;
_children = new ArrayList<NodeA>();
_depth = depth;
}
//probably want getters for _children and _value here
//this makes a new child, with its type depending on the depth of the tree it will
//be placed at. NodeB and NodeC will both inherit from NodeA
public void add(String value) {
switch (_depth) {
case 0:
_children.add(new NodeB(value, _depth+1));
break;
case 1:
_children.add(new NodeC(value, _depth+1));
break;
}
}
The add() method is going to create a new child for the node using the specified value. If you initialize the root of the tree as a NodeA with depth 0, you can add children to nodes and the tree should end up populated so that the next level contains all NodeB's, and the next all NodeC's. The code for NodeB and NodeC is super simple and could be replicated to create an arbitrary amount of Node levels (here is that code).
public class NodeB extends NodeA {
public NodeB(String value, int depth) {
super(value, depth);
}
//nothing else needed!
The code for NodeC is identical, except for the obvious replacements of B's with C's.
Hope this helps / is the kind of answer you wanted!