In order to practice data structures I'm implementing my own library of Trees. I've begun with BST and in following I'm about to implement AVL Tree, Red-Black Tree and maybe more. AVL & RBT are BST trees as well, so some class hierarchy is rather obvious. The problem I came into is that all those trees have other types of Nodes - AvlNode has balance factor flag, RgbNode has color flag, BstNode doesn't need any additional info (despite of references to parent, children and value which all Nodes need). So I've a hierarchy of Nodes and a hierarchy of Trees. I could give some flag attribute to BstNode and use it in extending classes but it is surely not a good way to do it.
The problem is how to deal with the fact that for example Bst.findNode() will return BstNode but in Avl I need AvlNode despite the findNode() methods will be the same in both (apart of return type).
I need help with planning the hierarchies or if those parallel hierarchies (as a code smell) are in general a bad idea, I need a workaround because I have no clue how to do it in proper way.
BstTree Class:
public class BstTree<T extends Comparable> implements Iterable
{
private BstNode<T> root;
public void addValue(T value)
{
BstNode node = new BstNode(value);
addNode(node);
}
public void addNode(BstNode<T> node)
{
...
}
public boolean removeNode(T value)
{
...
}
public BstNode findNode(T value)
{
...
}
//other less significant methods
}
BstNode class:
public class BstNode<T extends Comparable>
{
private static int lastId = 0;
private int id;
private T value;
private BstNode parent = null;
private BstNode leftChild = null;
private BstNode rightChild = null;
public BstNode(T value) {
this.id = ++lastId;
this.value = value;
}
public boolean isGreaterThan(BstNode n)
{
//...
}
public boolean hasLeftChild()
{
//...
}
public boolean hasRightChild()
{
//...
}
public boolean hasParent()
{
//...
}
public boolean isLeaf()
{
//...
}
public boolean hasOnlyOneChild()
{
//...
}
public BstNode getOnlyChild(BstNode node)
{
...
}
public boolean isLeftChildren()
{
...
}
public BstNode getConsequentNode()
{
...
}
}
I can guess that the separation of responsibilities above may not be perfect, if it's wrong then I might get some of the methods from Node to Tree class but this thing is not a big problem.
I would do something like this:
public abstract class BstTree<T extends Comparable,N extends BstNode<T,N>> {
private N root;
...
public void addValue(T value)
{
N node = newNode(value);
addNode(node);
}
public abstract N newNode(T value);
public void addNode(N node)
{
// ...
}
}
public class BstNode<T extends Comparable,N extends BstNode<T,N>>
{
private T value;
private N parent = null;
private N leftChild = null;
private N rightChild = null;
public BstNode(T value) {
this.value = value;
}
public N getOnlyChild(N node)
{
// ...
}
...
}
public class AVLTree<T extends Comparable> extends BstTree<T,AVLNode<T>> {
...
#Override
public AVLNode<T> newNode(T value) {
return new AVLNode<>(value);
}
}
public class AVLNode<T extends Comparable> extends BstNode<T,AVLNode<T>> {
...
public AVLNode(T value) {
super(value);
}
#Override
public AVLNode<T> getOnlyChild(AVLNode<T> node) {
return super.getOnlyChild(node);
}
...
}
Related
I have the following classes:
public class Node {
private int x;
private int y;
}
public abstract class Map {
protected Node[][] grid;
public abstract Set<Node> findNeighbours(Node node);
}
public class SquareMap extends Map {
private static final int VERTICAL_COST= 10;
private static final int HORIZONTAL_COST= 10;
private static final int DIAGONAL_COST = 14;
#Override
public Set<Node> findNeighbours(Node node) {
//return the 8 adjacent nodes
}
}
public class HexMap extends Map {
private static final int MOVE_COST = 10;
#Override
public Set<Node> findNeighbours(Node node) {
//return the 6 adjacent nodes
}
}
I would like to create a method like
public int calculateMoveCost(Node current, Node target, <whatever else is needed>) {}
Where I only pass in the nodes, and the logic in either the method, or the nodes, or the map recognizes what kind of map I'm using. My current solution looks like this:
private int calculateMoveCost(Node current, Node target, Map map) {
int cost;
if(isHexMap(map)) {
cost = map.getMoveCost();
} else {
if(isSquareMap(map)) {
if(verticalNeighbours(current, target)) {
cost = map.getVerticalMoveCost();
} else {
cost = map.getHorizontalMoveCost();
}
}
}
return cost;
}
When I look at this code, I think there has to be a better way to implement this. Could you recommend a nice object oriented way of implementing this? I can create any reference in any object, the goal is to have a nice solution. Thanks!
I do think there is a right answer for this, just have an abstract getMoveCost method on Map and implement it in each subclass. Then you can just call map.getMoveCost(from, to).
public abstract class Map {
protected Node[][] grid;
public abstract int getMoveCost(Node current, Node target);
public abstract Set<Node> findNeighbours(Node node);
}
public class SquareMap extends Map {
private static final int VERTICAL_COST= 10;
private static final int HORIZONTAL_COST= 10;
private static final int DIAGONAL_COST = 14;
#Override
public Set<Node> findNeighbours(Node node) {
//return the 8 adjacent nodes
}
#Override
public int getMoveCost(Node current, Node target) {
if(verticalNeighbours(current, target)) {
cost = getVerticalMoveCost();
} else {
cost = getHorizontalMoveCost();
}
}
}
I have a class structure something like this:
interface Composite {}
class Leaf implements Composite { public String val; }
class Node implements Composite {
private Node parent;
private Composite left;
private Composite right;
public void attachLeft(Composite c) {
left = c;
}
public void attachRight(Composite c) {
right = c;
}
public void attachLeft(Node n) {
left = n;
n.parent = this;
}
public void attachRight(Node n) {
right = n;
n.parent = this;
}
public void attachRandomly(Composite c) {
if ( ThreadLocalRandom.current().nextBoolean() ) {
attachRight(c);
} else {
attachLeft(c);
}
}
}
I have a method that generates a random tree (pseudocode):
// build tree
for some number of nodes :
make newNode
oldNode = randomly pick an existing node with an empty right/left
oldNode.attachRandomly(newNode)
// fill leaves of tree
for each node with empty right/left :
while node has empty right/left :
node.attachRandomly(new Leaf)
Unfortunately, because of static binding, the attachLeft/Right(Node c) methods never get called by attachRandomly. (attachRandomly is getting a Composite, so the Composite version of attachLeft/Right always gets called.) So my parent attribute is never getting set.
Now, I can think of a couple ways to make this work:
Remove the Node version of attachLeft/Right and just use instanceof and casting inside of the Composite version
Add a Node-specific version of attachRandomly
Option 1 feels yucky (instanceof! casting!) and option 2 just feels awkward because of the amount of extra code. Is there no better way to do this so that polymorphism can kick in and help me out here?
You could write it like this. This basic idea is called double dispatching. It introduces a new level of dispatching to each of your method calls, to allow dynamic binding to be used.
interface Composite {
void attachToLeft(Node newParent);
void attachToRight(Node newParent);
}
class Leaf implements Composite {
public String val;
#Override
public void attachToLeft(Node newParent) {
newParent.left = this;
}
#Override
public void attachToRight(Node newParent) {
newParent.right = this;
}
}
class Node implements Composite {
private Node parent;
private Composite left;
private Composite right;
public void attachLeft(Composite c) {
c.attachToLeft(this);
}
public void attachRight(Composite c) {
c.attachToRight(this);
}
#Override
public void attachToLeft(Node newParent) {
this.parent = newParent;
newParent.left = this;
}
#Override
public void attachToRight(Node newParent) {
this.parent = newParent;
newParent.right = this.
}
}
Currently studying for an exam, and I stuck at Generic Binary Tree
public interface BinaryTreeNode <T>{
public void setParent(T binaryTreeNodeImpl);
public void setLeft(T left);
public void setRight(T right);
public T getRoot() ;
public T getParent();
public void setValue(T string);
public T getLeft();
}
İt is my interface.
public class BinaryTreeNodeImpl <T> implements BinaryTreeNode <T>{
public T value;
private T Root;
private T right;
private T parent;
private T left;
public void setRight(T right) {
this.right = right;
( (BinaryTreeNode<T>) right).setParent( (T) this);
}
public T getRoot() {
return (T) Root;
}
public void setValue(T value) {
this.value=value;
}
public T getValue() {
return value;
}
public T getParent() {
return parent;
}
public void setParent(T binaryTreeNodeImpl) {
parent= binaryTreeNodeImpl;
}
public T getRight() {
return right;
}
public T getLeft() {
return left;
}
public void setLeft(T left) {
this.left = left;
( (BinaryTreeNode<T>) left).setParent((T) this);
}
}
it is my Binary Tree Implement .When I try to run. Bellow code I've got Value method is undefined for String.
BinaryTreeNode<String> root = new BinaryTreeNodeImpl<String>();
root.setValue("abc");
BinaryTreeNode<String> left = new BinaryTreeNodeImpl<String>();
left.setValue("xyz");
root.setLeft(left);
System.out.println(left.getParent().getValue());
System.out.println(root.getLeft().getValue());
I did not understand where I did wrong ? Should I create abstract method for that ?
The reason that you had the error is that getParent() and getLeft() return T, which is String, when you meant to return a node here.
Your references to root, parent, left, and right in your BinaryTreeNode interface have type T, but that is the type of data that the node needs to reference, not the node itself. Change the datatype of the return values and parameters of the methods that don't have anything to do with the value from T to BinaryTreeNode<T>. This will of course affect the same declarations in your implementing class BinaryTreeNodeImpl.
Your getParent() has a return type T; I am under the impression that you want this to be BinaryTreeNode<T> since a parent of a BinaryTreeNode should be a binary tree node (preferably of the same type).
Your current design is akin to saying that the parent of a BinaryTreeNode can be a String or an Integer or a cat and you are calling the getValue() on that, which obviously is not defined, hence the error.
Make the same edits to the return types in the method declarations in your interface.
I am new to generics and want to solve a little Task.
I want to give two Objects of type "V extends Comparable" to the class ComparePredicate and then check in method "isOk" if the int-value "value" of a Tree class is between these two Objects.
I choosed the compareTo method because Integer and V should be of type comparable but the compiler gives an error.
I think its just an syntactical problem.
So how do i need to write it correct. Hope you guys can help me.
Thanks for your answers.
Class ComparePredicate
public class ComparePredicate<V extends Comparable<V>> implements TreePredicate<V> {
V minEle;
V maxEle;
public ComparePredicate(V minEle, V maxEle) {
this.minEle = minEle;
this.maxEle = maxEle;
}
#Override
public boolean isOk(Tree<V> tree) {
return minEle.compareTo(Integer.valueOf(tree.getValue())) > 0 &&
maxEle.compareTo(Integer.valueOf(tree.getValue())) < 1;
//COMPILER ERROR: "The method compareTo(V) in the type Comparable<V> is not applicable for the arguments (Integer)"
return false;
}
}
Class Tree
public class Tree<T> {
private int value;
private final Tree<T> left;
private final Tree<T> right;
public Tree(int v, Tree<T> l, Tree<T> r) {
this.value = v;
this.left = l;
this.right = r;
}
public int getValue() {
return this.value;
}
public Tree<T> getLeft() {
return this.left;
}
public Tree<T> getRight() {
return this.right;
}
}
Change Tree class
static class Tree<T> {
private T value;
private final Tree<T> left;
private final Tree<T> right;
public Tree(T v, Tree<T> l, Tree<T> r) {
this.value = v;
this.left = l;
this.right = r;
}
public T getValue() {
return this.value;
}
// getters ...
}
And also change isOk()
#Override
public boolean isOk(Tree<V> tree) {
return minEle.compareTo(tree.getValue()) <= 0 &&
maxEle.compareTo(tree.getValue()) >= 0;
}
I'm trying to implement a Binary Tree in java with Generics, i searched and i find this question: Implementing Binary Tree in Java with Generic Comparable<T> data?, but i couldn't resolve my doubts. So i have two classes,
BST_Tree<T>
and
Node<T extends Comparable<T>>
I want that my implementation can:
Take every type of Object and put it inside the field key in Node
Compare every node with the key field
This is the code:
public class Node < T extends Comparable < T >> {
private T key;
private Node left;
private Node right;
private Node p;
public void setKey(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
public void setP(Node p) {
this.p = p;
}
public boolean getBolCompMin(T key) {
return this.key.compareTo(key) < 0;
}
}
My Node class is suppose to extend Comparable in order to compare the key.
This is my tree:
public class BST_Tree < T > {
private ArrayList < Node > nodes;
private Node root;
public BST_Tree(Node root) {
this.root = root;
}
public void insertNode(T key) {
Node z = new Node();
z.setKey(key);
Node x = this.root;
Node y = new Node();
while (x != null) {
y = x;
if (z.getBolCompMin(x.getKey())) {
x = x.getLeft();
} else {
x = x.getRight();
}
}
z.setP(y);
if (z.getBolCompMin(y.getKey())) {
y.setLeft(z);
} else {
y.setRight(z);
}
}
public void InOderWalk(Node x) {
if (x != null) {
InOderWalk(x.getLeft());
System.out.println(x.getKey());
InOderWalk(x.getRight());
}
}
public Node getRoot() {
return root;
}
}
My tree tries to set the key in node z but it fails. This is the error:
incompatible types: T cannot be converted to java.lang.Comparable
Thank you in advance!
Your
public class BST_Tree<T>
should be
public class BST_Tree<T extends Comparable<T>>
And every Node variable inside your BST_Tree and Node classes should be Node<T>.
This would ensure that you can only instantiate your BST_Tree class with element types that implement Comparable.