I want to write a custom iterator for BinaryTree. This iterator should return Node<?> objects. I get compile error in file InorderIterator in lines with recursive call to fillList: fillList(currentNode.getLeft());
The error is: Error:(14, 37) java: incompatible types: rclib.Node cannot be converted to T
Can somebody explain me why my approach doesn't work? Or how to fix it
Node.java
package rclib;
public class Node<T extends Comparable<T>> {
T key;
Node<T> left;
Node<T> right;
public Node(T key, Node left, Node right) {
this.key = key;
this.left = left;
this.right = right;
}
public Node(T key) {
this(key, null, null);
}
public Node<T> getLeft() {
return left;
}
public Node<T> getRight() {
return right;
}
public T getKey() {
return key;
}
}
InorderIterator.java
package rclib;
import java.util.*;
public class InorderIterator<T extends Node<?>> implements Iterator<T> {
LinkedList<T> list;
public InorderIterator(T root) {
list = new LinkedList<T>();
fillList(root);
}
public void fillList(T currentNode) {
if (currentNode == null) return;
fillList(currentNode.getLeft());
list.add(currentNode);
fillList(currentNode.getRight());
}
#Override
public boolean hasNext() {
return !list.isEmpty();
}
#Override
public T next() {
return list.removeFirst();
}
}
AVLTree.java
package rclib;
public class AVLTree<T extends Comparable<T>> implements Iterable<Node<T>>{
private Node<T> root;
#Override
public Iterator<Node<T>> iterator() {
return new InorderIterator<Node<T>>(root);
}
}
You should perhaps do something like that:
package rclib;
import java.util.*;
public class InorderIterator<T extends Comparable<T>> implements Iterator<Node<T>> {
LinkedList<Node<T>> list;
public InorderIterator(Node<T> root) {
list = new LinkedList<Node<T>>();
fillList(root);
}
public void fillList(Node<T> currentNode) {
if (currentNode == null) return;
fillList(currentNode.getLeft());
list.add(currentNode);
fillList(currentNode.getRight());
}
#Override
public boolean hasNext() {
return !list.isEmpty();
}
#Override
public Node<T> next() {
return list.removeFirst();
}
}
You have to explicitly specify that you use Node and not ? extends Node which might finally be not qualified for the correct usage.
public static class InorderIterator<T extends Comparable<T>> implements Iterator<Node<T>> {
LinkedList<Node<T>> list;
public InorderIterator(Node<T> root) {
list = new LinkedList<>();
fillList(root);
}
public void fillList(Node<T> currentNode) {
if (currentNode == null) return;
fillList(currentNode.getLeft());
list.add(currentNode);
fillList(currentNode.getRight());
}
#Override
public boolean hasNext() {
return !list.isEmpty();
}
#Override
public Node<T> next() {
return list.removeFirst();
}
}
Related
This one our first class AbstractLinkedList<T>
public abstract class AbstractLinkedList<T> {
public class Node<T> {
public T value;
Node<T> next;
public Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
Node<T> head;
public Node<T> getHead() {
return head;
}
public void addFirst(T value) {
head = new Node<>(value, head);
}
public void addLast(T value){
if(head==null)
head = new Node<>(value, null);
else {
Node<T> node = head;
while (node.next!=null)
node = node.next;
node.next = new Node<>(value, null);
}
}
public void print(){
System.out.println(toString());
}
#Override
public String toString(){
if(head==null) return "boş";
String r="";
Node<T> node=head;
while(node!=null) {
r += node.value + (node.next!=null?" ":"");
node=node.next;
}
return r;
}
public abstract void insertInOrder(T value);
public abstract AbstractLinkedList<T> reverse();
public abstract AbstractLinkedList<T> concatenate(AbstractLinkedList<T> list);
}
This is second one Odev1LinkedList implements Comparable<T>> extends AbstractLinkedList<T>
public class Odev1LinkedList<T extends Comparable<T>> extends AbstractLinkedList<T> {
#Override
public AbstractLinkedList<T> reverse() {
Odev1LinkedList a = new Odev1LinkedList();
Node<T> root = new Node(this, head);
Node<T> iter = root;
Node<T> temp ;
a.head = null;
do {
temp = iter;
a.addFirst(temp.value);
iter = iter.next;
}while (temp !=root );
return a;
}
When I run this code example.reverse should make reverse and return LinkedList without changing ORIGINAL LinkedList.
But its return without reversing
You can't use the < operator on arbitrary objects. It's only defined for primitive numbers. Take a look into the specification.
If your object of type T implements Comparable<T> you can use head.value.compareTo(value) < 0.
If you want your objects of type T to implement Comparable<T> you have to go to your class declaration and write
public class MyLinkedList<T extends Comparable<T>> { ... }
Currently as an exercise to practicing SOLID principles and basic data structures, I am trying to implement linked list type structures with as much code reuse as possible. Currently, I have:
package structures.linked;
public class SingleNode<T> {
private T data;
private SingleNode<T> next;
public SingleNode(T data, SingleNode<T> next) {
this.data = data;
this.next = next;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public SingleNode<T> getNext() {
return next;
}
public void setNext(SingleNode<T> next) {
this.next = next;
}
}
and...
package structures.linked;
public class DoubleNode<T> extends SingleNode<T> {
private DoubleNode<T> prev;
public DoubleNode(T data, DoubleNode<T> next, DoubleNode<T> prev) {
super(data, next);
this.prev = prev;
}
public DoubleNode<T> getPrev() {
return prev;
}
public void setPrev(DoubleNode<T> prev) {
this.prev = prev;
}
public DoubleNode<T> getNext() {
return (DoubleNode<T>) super.getNext();
}
public void setNext(DoubleNode<T> next) {
super.setNext(next);
}
}
It seems to me that getNext() inside of DoubleNode<T> is a violation of Liskov's substitution principle. Is this the case? Is there a better way to implement this while still reusing the code in SingleNode<T> and without breaking SOLID principles?
You can do this by using an abstract class with additional generic parameter:
public abstract class AbstracteNode<T, B extends AbstracteNode<T, ?>> {
private T data;
private B nextNode;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public void setNext(B inNextNode){
this.nextNode = inNextNode;
}
public B getNext() {
return nextNode;
}
}
Then extending it with the correct types for B:
(In case of SingleNode you do this only for the reason that developers using it have only to provide T)
public class SingleNode<T> extends AbstracteNode<T, SingleNode<T>>{}
And
public class DoubleNode<T> extends AbstracteNode<T, DoubleNode<T>> {
private DoubleNode<T> previousNode;
public DoubleNode<T> getPrevious() {
return previousNode;
}
public void setPrevious(DoubleNode<T> inPreviousNode) {
this.previousNode = inPreviousNode;
}
}
Now your test should work without code duplication and without casting:
public class Test {
public static void main(String argv[]){
SingleNode<Integer> singleNode = new SingleNode<>();
SingleNode<Integer> nextForSingle = singleNode.getNext();
DoubleNode<Double> doubleNode = new DoubleNode<>();
DoubleNode<Double> previousForDouble = doubleNode.getPrevious();
DoubleNode<Double> nextForDouble = doubleNode.getNext();
}
}
As a homework I'm creating a SingleLinkedNode class that implements a Node interface.
Node Interface
public interface Node <T> {
static final String NULL_NODE_ERROR = "Node can't be null";
public void setNextNode(Node nextNode) throws NullPointerException;
public void setIndex(int index);
public int getIndex();
public T getData();
public Node getNextNode();
}
SingleLinkedNode class
public class SingleLinkedNode<T> implements Node<T> {
private int index;
private T data;
private SingleLinkedNode nextNode;
public SingleLinkedNode() {
}
public SingleLinkedNode(int index) {
this.index = index;
}
public SingleLinkedNode(int index, SingleLinkedNode nextNode) {
this.index = index;
this.nextNode = nextNode;
}
#Override
public void setNextNode(SingleLinkedNode nextNode) throws NullPointerException{
if (nextNode == null){
throw new NullPointerException(NULL_NODE_ERROR);
}
this.nextNode = nextNode;
}
#Override
public void setIndex (int index){
this.index = index;
}
#Override
public int getIndex() {
return this.index;
}
#Override
public T getData() {
return this.data;
}
#Override
public SingleLinkedNode getNextNode() {
return this.nextNode;
}
}
In the setNextNode(SingleLinkedNode nextNode) method of the class it says that I'm not implementing the setNextNode(Node nextNode) method of the interface even though SingleLinkedNode implements Node.
But if I leave the class method exactly as the interface one it says that Node can't be converted to SingleLinkedNode, pretty obvious.
Is there any right way of overriding this method and being sure that the method only accepts SingleLinkedNode objects as arguments?
I thought about casting but I'm not sure if that the right way.
Thank you all the solution was as follows
#Override
public void setNextNode(Node nextNode) throws NullPointerException, IllegalArgumentException{
if (nextNode == null){
throw new NullPointerException(NULL_NODE_ERROR);
}
if ( ! (nextNode instanceof SingleLinkedNode) ) {
throw new IllegalArgumentException ("Node is not SingleLinkedNode");
}
this.nextNode = (SingleLinkedNode) nextNode;
}
I'm trying to build an raw type BST, with Comparable<T>. The thing is somehow my declarations do something wrong, because I use in Node class type Comparable<type> and in BST class it errors with
The method setParent(Node<Comparable<Comparable<type>>>) in the type
Node<Comparable<type>> is not applicable for the arguments (Node<Comparable<type>>)
BinarySearchTree.java /lab2/src line 22 Java Problem
Node.java:
public class Node <type> {
private Comparable<type> key;
private Node <Comparable<type>> parent;
private Node <Comparable<type>> leftChild;
private Node <Comparable<type>> rightChild;
public Node(Comparable<type> key, Node <Comparable<type>> leftChild, Node <Comparable<type>> rightChild) {
this.setKey(key);
this.setLeftChild(leftChild);
this.setRightChild(rightChild);
}
public void setKey(Comparable<type> key) {
this.key = key;
}
public Comparable<type> getKey() {
return key;
}
public void setParent(Node<Comparable<type>> y) {
this.parent = y;
}
public Node <Comparable<type>> getParent() {
return parent;
}
public void setLeftChild(Node <Comparable<type>> leftChild) {
this.leftChild = leftChild;
}
public Node <Comparable<type>> getLeftChild() {
return leftChild;
}
public void setRightChild(Node <Comparable<type>> rightChild) {
this.rightChild = rightChild;
}
public Node <Comparable<type>> getRightChild() {
return rightChild;
}
}
BinarySearchTree.java:
import java.util.Iterator;
public class BinarySearchTree<type> implements SortedSet<type> {
private Node <Comparable<type>> root;
public void insert(Node <Comparable<type>> z) {
Node <Comparable<type>> y = null;
Node <Comparable<type>> x = root;
while (x != null) {
y = x;
if (z.getKey() < x.getKey()) { // ERROR '<' is undefined for type...
x = x.getLeftChild(); // PARAM TYPE ERROR
} else {
x = x.getRightChild(); // PARAM TYPE ERROR
}
}
z.setParent(y);
if (y == null) {
root = z;
} else if (z.getKey() < y.getKey()) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
}
Consider to refactoring to the following code
import java.util.SortedSet;
public abstract class BinarySearchTree<T extends Comparable<T>> implements SortedSet<T> {
private Node<T> root;
class Node<T extends Comparable<T>> {
private T key;
private Node<T> parent;
private Node<T> leftChild;
private Node<T> rightChild;
public Node(T key, Node<T> leftChild, Node<T> rightChild) {
this.setKey(key);
this.setLeftChild(leftChild);
this.setRightChild(rightChild);
}
public void setKey(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setParent(Node<T> y) {
this.parent = y;
}
public Node <T> getParent() {
return parent;
}
public void setLeftChild(Node <T> leftChild) {
this.leftChild = leftChild;
}
public Node <T> getLeftChild() {
return leftChild;
}
public void setRightChild(Node <T> rightChild) {
this.rightChild = rightChild;
}
public Node <T> getRightChild() {
return rightChild;
}
}
public void insert(Node<T> z) {
Node<T> y = null;
Node<T> x = root;
while (x != null) {
y = x;
if (z.getKey().compareTo(x.getKey()) < 0) {
x = x.getLeftChild();
} else {
x = x.getRightChild();
}
}
z.setParent(y);
if (y == null) {
root = z;
} else if (z.getKey().compareTo((T) y.getKey()) <0) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
}
}
I'm trying to create a b-tree class that implements the collection interface shown below. The Issue here is that the add method takes in an object and my node classes setleftNode takes in a Node of a generic type "T". Thus I'm getting method cant be applied to given type error when compiling. :
B-Tree Class:
public class BST<T> implements Collection<T>{
private Node<T> _root;
private Node<T> _current;
private Random _rnd = new Random();
public BST(Node<T> root) {
_root = root;
}
public Node<T> getRoot(){
return _root;
}
#Override
public Iterator iterator() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public boolean add(Object e) {
if (this._root != null){
if(this._root.getLeftNode() == null){
this._root.setLeftNode(e);
return true;
}
}
return false;
}
Node Class:
public class Node<T>{
private T _value;
private Node<T> _left;
private Node<T> _right;
public Node (T value){
_value = value;
}
public T getValue(){
return _value;
}
public void setLeftNode(Node<T> node){
_left= node;
}
public void setRightNode(Node<T> rNode){
_right = rNode;
}
public Node getRightNode(){
return _right;
}
public Node getLeftNode(){
return _left;
}
}
If BST<T> implements Collection<T> it should have add(T e). And inside setLeftNode(new Node<T>(e))):
#Override
public boolean add(T e) {
if (this._root != null){
if(this._root.getLeftNode() == null) {
this._root.setLeftNode(new Node<T>(e));
return true;
}
}
return false;
}
you want your BST class to work with the type T, so you should define the add method likewise
public boolean add(T e) {
...
}
BST<String> bst = new BST<String>();
bst.add(new String("Hello"))