I have (recursively) defined a class for implementing a binary tree (in Java):
class BinaryTree {
protected int key;
protected BinaryTree left, right;
// some methods...
}
from which I want to implement a binary search tree, like this:
class BinarySearchTree extends BinaryTree {
// ...
public BinarySearchTree search(int x) {
if (x == key)
return this;
if (x < key)
if (left != null)
return left.search(x); // (*)
else
if (right != null)
return right.search(x); // (*)
return null;
}
}
but of course the lines marked with // (*) won't compile beacause left and right are just BinaryTrees, without any search() method.
So I am wondering if theres is a way to define BinarySearchTree from the BinaryTree superclass but with left and right being actually BinarySearchTrees.
Or maybe there is a better way of implementing the relationship between binary trees and the search ones: should I define a separate Node class? should I use templates? should I avoid recursive definitions at all? ...
You can use recursive generics.
Define a recursive generic type variable, say, B:
class BinaryTree<B extends BinaryTree<B>> {
and make your fields of this type:
protected B left, right;
Then define:
class BinarySearchTree extends BinaryTree<BinarySearchTree> {
Now left and right are of type BinarySearchTree too, allowing you to call left.search and right.search.
I feel BinaryTreeNode should be created as an inner class ofBinaryTree.java. BinaryTreeNode can have int data, and two references of type BinaryTreeNode for left and right node
BinaryTree.java should have an reference of type BinaryTreeNode which will be the root of the tree.
Now BinarySearchTree extends BinaryTree looks good, you can include an method in it as below signature.
BinaryTreeNode `search( int k, BinaryTreeNode root)`
Now you can define the recursive method.
Please see Sample code with basic skeleton.
BinaryTreeNode.java
public class BinaryTreeNode {
private int data;
private BinaryTreeNode left, right;
public BinaryTreeNode(int data) {
this.setData(data);
}
public BinaryTreeNode getLeft() {
return left;
}
public void setLeft(BinaryTreeNode left) {
this.left = left;
}
public BinaryTreeNode getRight() {
return right;
}
public void setRight(BinaryTreeNode right) {
this.right = right;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
BinaryTree.java
public class BinaryTree {
protected BinaryTreeNode root;
// other basic methods needed for creating the Binary tree.
}
BinarySearchTree.java
public class BinarySearchTree extends BinaryTree {
public BinaryTreeNode search(int k) {
return search(k, root);
}
private BinaryTreeNode search(int k, BinaryTreeNode root) {
if (root.getData() == k) {
return root;
}
if (root.getData() < k) {
return search(k, root.getRight());
} else {
return search(k, root.getLeft());
}
}
// add other methods needed for creating the Binary search tree.
// also override the methods which needs to be modified for their behavior
// for binary search tree
}
I am fairly new to Java and I need to make a linked list. I was told that I need to make a class called "Node" to store each element. I've written the class:
public class Node()
{
public T data;
public Node next;
public Node(T data, Node next)
{
this.data = data;
this.next = next;
}
public Node getNext()
{
return next;
}
public T getData()
{
return data;
}
}
However, I am not allowed to make a separate class, it has to be within the LinkedList class. I understand how to make an inner class of something like an imported iterator, but the "Node" is not imported. How would I do this?
public class Linked{
class Node{
int value;
Node next;
Node(int data,Node next){
value=data;
this.next=next;
}
Node getNext(){
return next;}
}
//Rest of the linked list methods
}
This is called an inner class which is nothing but a class nested inside another class. When we know that a class has no existence outside the main class we nest that class inside the main class i.e as we know that this node class cannot be used outside anywhere in the program thus we made this class an inner class.
I build a class 'AbstractTree' and create another class 'SearchTree' which extends 'AbstractTree'.
public class SearchTree<TreeNode> extends AbstractTree<TreeNode> {
TreeNode root;
public SearchTree(){
root=new TreeNode();
}
}
There is an error occured in the constructing method. It says that it cannot initialize the type TreeNode.
TreeNode is another class I build.
public class TreeNode<E> extends AbstractNode<E> {
E element;
TreeNode<E> parent;
ArrayList<TreeNode<E>> children;
public TreeNode(){
parent=new TreeNode<E>();
children=new ArrayList<TreeNode<E>>();
}
//...some other methods
}
Your declaration of SearchTree has an error. In fact public class SearchTree<TreeNode> extends AbstractTree<TreeNode> {is using TreeNode as a generic class Type parameter and not as the TreeNode class that you are intending to use here.
And so the generic type parameter that you called TreeNode is now hidding usage of the real TreeNode class. See attached image
Therefore I would change your SearchTree class the following way:
public class SearchTree<E> extends AbstractTree<TreeNode<E>> {
TreeNode<E> root;
public SearchTree()
{
root = new TreeNode<E>();
}
}
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);
}
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!