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>();
}
}
Related
I want to make a binary tree keep node as heap so that
I try to make a generic in generic but I got some problem about it.
1-)I could not figure out two layer generic is it possible in Java.
2-)I adding tree as number but when I try to return node I dont now assign what and can I reach it methods if it can be return .
Binary Search Tree Heap Tree
public class BSTHeapTree <E extends Comparable<? extends Comparable<?>>>{
BinarySearchTree<E<T>> root; //error
public BSTHeapTree() {
root = new BinarySearchTree<>(); // error
}
int add(E _data) {
= root.getRoot(); //Assign what
return 0;
}
}
Binary Search Tree
public class BinarySearchTree<E extends Comparable<E>>{
private Node<E> head;
public BinarySearchTree() {
head = null;
}
public Node<E> getRoot() {
return head;
}
private static class Node<E extends Comparable<E>>{
E data;
Node<E> lBranch;
Node<E> rBranch;
}
}
Heap
public class Heap<E extends Comparable<E>> implements Comparable<Heap<E>>{
private E[] heapData;
}
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.
I am designing some java objects to represent graphs and trees. For my use case I will be using both data types but I also want my graph algorithms to work on my trees.
import java.util.List;
public interface Node<T> {
T getValue();
List<? extends Node<T>> getNeighbors();
void addNodes(List<? extends Node<T>> nodes);
}
public interface TreeNode<T> extends Node<T> {
List<? extends TreeNode<T>> getChildren();
void addChildren(List<? extends TreeNode<T>> treeNodes);
#Override
default List<? extends Node<T>> getNeighbors() {
return getChildren();
}
#Override
default void addNodes(List<? extends Node<T>> nodes) {
if(nodes.getClass().isInstance(getChildren().getClass())) {
addChildren((List<? extends TreeNode<T>>) nodes);
} else {
throw new RuntimeException("Type error!");
}
}
}
My question is about how I'm dealing with addNodes method in the Node interface in the TreeNode interface. The addNodes method has to be in the Node interface because I want to allow people to write code that can add nodes to graphs. However, I also don't want people to add arbitrary nodes to a tree node(for example adding a graph node to a tree node).
In order to prevent this, I'm checking the type of nodes at runtime and throwing an exception if the type is not right. I'm just wondering if this is the best way to accomplish what I want or if there is a better practice?
Thanks for helping :)
If I understand correctly, what you want is (a variation on) the so-called curiously recurring template pattern. The Node type needs to be parameterized not only by its payload type (T) but also by the type of nodes it can be used with. So you want something like:
public interface Node<T, N extends Node<T, N>> {
T getValue();
List<N> getNeighbors();
void addNodes(List<N> nodes);
}
public interface TreeNode<T> extends Node<T, TreeNode<T>> {
List<TreeNode<T>> getChildren();
void addChildren(List<TreeNode<T>> treeNodes);
#Override
default List<TreeNode<T>> getNeighbors() {
return getChildren();
}
#Override
default void addNodes(List<TreeNode<T>> nodes) {
addChildren(nodes);
}
}
Demo (shows compilation only): https://ideone.com/44qrmX
The way I see it, Node is a container for some data. Tree and Graph are two ways to maintain relationships between Nodes. So perhaps three classes should be defined:
import java.util.List;
public class Node<T> {
private T value;
public Node(T value) { this.value = value; }
T getValue() { return value; }
}
public abstract class Tree<T> {
private Node<T> root;
public abstract List<? extends Node<T>> getChildren();
public abstract void addChildren(List<? extends Node<T>> nodes);
public Tree(Node<T> root) { this.root = root; }
}
public abstract class Graph<T> {
private Node<T> root;
public abstract List<? extends Node<T>> getNeighbors();
public abstract void addNeighbors(List<? extends Node<T>> nodes);
public Graph(Node<T> root) { this.root = root; }
}
EDIT: If you want to have shared traversal algorithms, you can put them in separate classes and have the Tree and Graph use similar semantics like this:
// common semantics for node containers
public interface NodeContainer<T> {
List<? extends Node<T>> getRelatedNodes();
}
public abstract class Tree<T> implements NodeContainer<T> {
... // same as above
#Override
public List<? extends Node<T>> getRelatedNodes() {
return getChildren();
}
}
public class NodeContainerTraversal {
public void bfs (NodeContainer<?> container) {
...
}
}
I'm trying to implement a tree such that the nodes are generic:
public class BinarySearchTree<U extends BinarySearchTree.Node, T extends Comparable<? super T>>
{
public U root;
...
public class Node {
T data;
U left;
U right;
public Node(T data) {
this.data = data;
left = null;
right = null;
}
}
}
But when I try to do an assignment in one of my methodsI get a "Expected U but found BinarySearchTree.Node:
public void display(U root) {
if (root != null) {
display(root.left); // gives compile time error
System.out.print(" " + root.data);
display(root.right); // gives compile time error
}
}
Since Node is not static, every Node instance belongs to a containing BinarySearchTree instance. But it is not possible with generics to specify to which one it belongs. So if you specify BinarySearchTree.Node it can belong to any BinarySearchTree. Since you also used a raw type (don't ignore the warnings!) it is not known what U is. Therefore, Java cannot check that root.left and root.right are of the same type, which is why you get the error.
You can fix the compile error by specifying the class as follows:
class BinarySearchTree<U extends BinarySearchTree<U,T>.Node, T extends Comparable<? super T>>
{ ... }
but this does not fix the underlying problem that the nodes can belong to any containing BinarySearchTree, which probably is not what you want.
If you really want use a generic node type, you could make it static you, so that it doesn't belong to containing instances anymore:
public static class Node<U,T>
{
...
}
But I question the need to have a generic node class in the first place. Usually, such nodes are considered an implementation detail and you want to have full control over creating them from within your class. That cannot work with a generic node because your class doesn't know what kind of nodes to instantiate.
So I would define your BinarySearchTree class as follows:
public class BinarySearchTree<T extends Comparable<? super T>>
{
private Node<T> root;
private static class Node<T>
{
T data;
Node<T> left;
Node<T> right;
}
...
}
You should rewrite the class definition to
public class BinarySearchTree<U extends BinarySearchTree<U, T>.Node, T extends Comparable<? super T>>
I'm writing a generic class:
public class Node<T> {
private Node<T> parent = null;
private List<? extends Node<T>> children = null;
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
if(this.parent != null){
// Remove current parent's children references
this.parent.getChildren().remove(this);
}
// Add references
this.parent = parent;
parent.getChildren().add(this);
}
public List<? extends Node<T>> getChildren() {
return children;
}
}
I want some other class which subclass this Node. This code cannot be compiled with the error on line parent.getChildren().add(this);. Because I declared getChildren() with List<? extends Node<T>> as return type, and 'this' is type Node<T>.
Is there anyway to solve this?
Declare the list as:
List<Node<T>> children
You may still put instances of subclasses in the list.
If you leave it as an unknown type, the compiler can't ensure which class it is typed as. Eg it might be typed as SubClassA, but you're adding SubClassB and it has no way to know based on the declared type, which is all the compiler has to go on. At runtime, while the type of list and child might match, the compiler can't assert.