I'm getting the type safety warning everywhere in the program and I'm pretty sure I did something wrong the with the usage of generics. The warning is displayed in code mostly that has Node involved. Please point out the parts where my syntax is possibly not the most ideal and recommend changes to my code. Appreciate any help!
Removing the in Node class works!
public class BinaryTree<T extends Comparable<T>> {
private class Node<T>{
private T data;
private Node left;
private Node right;
// left and right child do not have to nessary exist
public Node ( T data) {
this.data = data;
this.left = null;
this.right = null;
}}
private Node<T>root;
private int count = 0;
public void add( T data) {
if ( isEmpty()) {
root = new Node(data);
count++;
}
else {
insert(data, root);
count++;
}
}
public boolean isEmpty() {
return root == null;
}
public T getRoot() {
if ( root.data == null) {
System.out.println("Root is empty");
return null;
}
else {
return root.data;
}}
/*
* Checking if the data is larger or lesser than the parent's data
* If the data is smaller than the parent's data, node.left is created
* If the data is bigger than the parent's data, node.right is created
*/
private void insert( T data, Node<T>node) {
/*
* If 1st obj is less than the 2nd obj return a neg
* if 1st obj is more than the 2nd obj return a pos
* if equal return 0
*/
int compare = data.compareTo(node.data);
if ( compare < 1 ){
if (node.left == null ) {
node.left = new Node(data);
}
// make node.left if it is filled
else {
insert(data, node.left);
}
}
else {
if ( node.right == null) {
node.right = new Node(data);
}
else {
insert( data, node.right);
}
}
}
public int getSize() {
return count;
}
Related
Here is the Node class:
public class BSTNode<T extends Comparable<? super T>> {
private T data;
private BSTNode<T> left;
private BSTNode<T> right;
BSTNode(T data) {
this.data = data;
}
T getData() {
return data;
}
BSTNode<T> getLeft() {
return left;
}
BSTNode<T> getRight() {
return right;
}
void setData(T data) {
this.data = data;
}
void setLeft(BSTNode<T> left) {
this.left = left;
}
void setRight(BSTNode<T> right) {
this.right = right;
}
}
Here is my BST class with main driver method:
import java.util.NoSuchElementException;
public class BST<T extends Comparable<? super T>> {
private BSTNode<T> root;
private int size;
BST() {
root = null;
}
public void add(T data) {
if (data == null) {
throw new IllegalArgumentException("Error: Data can't be null");
}
root = rAdd(root, data);
}
private BSTNode<T> rAdd(BSTNode<T> current, T data) {
if (current == null) {
size++;
return new BSTNode<T>(data);
} else if (data.compareTo(current.getData()) < 0) {
current.setLeft(rAdd(current.getLeft(), data));
} else if (data.compareTo(current.getData()) > 0) {
current.setRight(rAdd(current.getRight(), data));
}
return current;
}
public T remove(T data) {
if (data == null) {
throw new IllegalArgumentException("Error: data can't be null");
}
BSTNode<T> dummy = new BSTNode<>(null);
root = rRemove(root, data, dummy);
return dummy.getData();
}
private BSTNode<T> rRemove(BSTNode<T> current, T data, BSTNode<T> dummy) {
if (current == null) {
throw new NoSuchElementException("Error: Data not present");
} else if (data.compareTo(current.getData()) < 0) {
current.setLeft(rRemove(current.getLeft(), data, dummy));
} else if (data.compareTo(current.getData()) > 0) {
current.setRight(rRemove(current.getRight(), data, dummy));
} else {
System.out.println("Data found ... ");
dummy.setData(current.getData());
size--;
if (current.getRight() == null && current.getLeft() == null) {
if (current.equals(root)) {
this.root = null;
}
return null;
} else if (current.getLeft() != null) {
return current.getLeft();
} else if (current.getRight() != null) {
return current.getRight();
} else {
BSTNode<T> dummy2 = new BSTNode<>(null);
current.setRight(removeSuccessor(current.getRight(), dummy2));
current.setData(dummy2.getData());
}
}
return current;
}
private BSTNode<T> removeSuccessor(BSTNode<T> current, BSTNode<T> dummy) {
if (current.getLeft() == null) {
dummy.setData(current.getData());
return current.getRight();
} else {
current.setLeft(removeSuccessor(current.getLeft(), dummy));
}
}
public List<T> inorder(BSTNode<T> root) {
ArrayList<T> inorderContents = new ArrayList<T>();
if (root == null) {
return inorderContents;
}
inorderR(inorderContents, root);
return inorderContents;
}
private void inorderR(ArrayList<T> inorderContents, BSTNode<T> current) {
if (current == null) {
return;
}
inorderR(inorderContents, current.getLeft());
inorderContents.add(current.getData());
inorderR(inorderContents, current.getRight());
}
public BSTNode<T> getRoot() {
// DO NOT MODIFY THIS METHOD!
return root;
}
public int size() {
// DO NOT MODIFY THIS METHOD!
return size;
}
public static void main(String[] args) {
BST bst3 = new BST<>();
bst3.add(1);
bst3.add(0);
bst3.add(5);
bst3.add(4);
bst3.add(2);
bst3.add(3);
System.out.println(bst3.inorder(bst3.getRoot() ));
bst3.remove(1);
System.out.println(bst3.inorder(bst3.getRoot() ));
}
}
My IDE (IntelliJ) says I am missing a return statement for my removeSuccessor(BSTNode current, BSTNode dummy) method but I expected it to recurse to the base case reinforcing the unchanged nodes.
As a result when I try and remove from a two child node it returns zero although the one child and zero child cases work .
Please can someone tell me what is wrong with my two child node remove case? Thanks, Sperling.
First, you need to modify the if-else by changing the conditions:
if (current.getLeft() != null && current.getRight() == null) {
return current.getLeft();
} else if (current.getRight() != null && current.getLeft() == null) {
return current.getRight();
}
instead of the same without the 2nd arguments of && in the rRemove() method.
Then, use this:
private BSTNode<T> removeSuccessor(BSTNode<T> current, BSTNode<T> dummy) {
if (current.getLeft() == null) {
dummy.setData(current.getData());
return current.getRight();
} else {
current.setLeft(removeSuccessor(current.getLeft(), dummy));
return current;
}
}
Meaning of this method is as follows: delete the lowest value in the tree and return new root, as well as remember the value using dummy.
If we get nothing to the left, it's trivial - we delete current node, return getRight() and set a value to dummy.
On the other hand, if we get something to the left then we know that our current node will be the root, but before we return it we need to remove the lowest entry to the left, and so we use the function recursively, also setting current.left to be it's return value to properly transform the tree. We pass dummy so that it can get a value when the first case occurs, and then it's communicated to the highest call (inside the first function).
It's also possible to do it without recursion:
private BSTNode<T> removeSuccessor2(BSTNode<T> current, BSTNode<T> dummy) {
BSTNode<T> root = current;
BSTNode<T> prev = null;
while(current.getLeft() != null) {
prev = current;
current = current.getLeft();
}
/* current.getLeft == null */
//we will delete current
if (prev == null) { //no loop iterations -- current is the root
dummy.setData(current.getData());
return(current.getRight());
}
else {//some iterations passed, prev.getLeft() == curret
dummy.setData(current.getData());
prev.setLeft(current.getRight());
return root;
}
}
With dummy we return the value, the rest is transforming the tree.
Note: It doesn't work in my version for current == null. You should be able to modify it easily, though. Also, for clarity I didn't pull the dummy.setData... before if...else etc. Modify it as you wish!
I'm trying to write an implementation of a BinaryTree whose object can be of any type that implements Comparable. However, I realize that won't completely work. For example, A String and a Double wouldn't be able to be inserted into the same tree, even though they both implement Comparable.
So, I would like to know if it's possible to write the code such that the BinaryTree can be instantiated with any value whose type implements Comparable, but any ensuing elements added to the tree must all share the same supertype as the root's value.
Here's the code I have so far:
public class BinaryTree {
private Node root;
public BinaryTree() {
this.root = null;
}
public Node lookup(Comparable<Object> value) {
return lookup(this.root, value);
}
private Node lookup(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node lookupNonRecursively(Comparable<Object> value) {
return lookupNonRecursively(this.root, value);
}
private Node lookupNonRecursively(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else {
Node root = node;
boolean found = false;
while (!found && root != null) {
if (root.value.compareTo(value) < 0) {
if (root.left == null) {
root.left = match = new Node(value);
found = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = match = new Node(value);
found = true;
} else {
root = root.right;
}
}
}
}
}
return match;
}
public Node insert(Comparable<Object> value) {
return insert(this.root, value);
}
private Node insert(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
if (node.value.compareTo(value) <= 0) {
insert(node.left, value);
} else {
insert(node.right, value);
}
}
return node;
}
public Node insertNonRecursively(Comparable<Object> value) {
return insertNonRecursively(this.root, value);
}
private Node insertNonRecursively(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
Node root = node;
boolean inserted = false;
while (!inserted) {
if (node.value.compareTo(root.value) < 0) {
if (root.left == null) {
root.left = node = new Node(value);
inserted = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = node = new Node(value);
inserted = true;
} else {
root = root.right;
}
}
}
}
return node;
}
public static class Node {
private Node left;
private Node right;
private Comparable<Object> value;
public Node(Comparable<Object> value) {
this.left = null;
this.right = null;
this.value = value;
}
}
}
And as a test, this will throw the error, The method insert(Comparable<Object>) in the type BinaryTree is not applicable for the arguments (Integer), if I try to run code like the following:
BinaryTree tree = new BinaryTree();
tree.insert(new Integer(1));
You can see I've implemented some different BinaryTree methods for this class, but the same rules would need to apply: any value passed into lookup() or insert() would also need to share the root's supertype. I have a feeling this is where some variant of <T extends Comparable<? super T>> is going to come into play, but my mind is just not figuring this one out.
Any ideas for how I might accomplish this?
As noted by #jp-jee, here's my solution (also with logic and other bugs fixed from untested first attempt), which works beautifully:
public class BinaryTree<T extends Comparable<T>> {
private Node<T> root;
public BinaryTree() {
this.root = null;
}
public Node<T> lookup(T value) {
return lookup(this.root, value);
}
private Node<T> lookup(Node<T> node, T value) {
Node<T> match = null;
if (match != node) {
if (value.equals(node.value)) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node<T> lookupNonRecursively(T value) {
return lookupNonRecursively(this.root, value);
}
private Node<T> lookupNonRecursively(Node<T> node, T value) {
Node<T> match = null;
if (match != node && value != null) {
if (value.equals(node.value)) {
match = node;
} else {
Node<T> searchRoot = node;
boolean found = false;
while (!found && searchRoot != null) {
if (value.equals(searchRoot.value)) {
match = searchRoot;
found = true;
} else if (value.compareTo(searchRoot.value) < 0) {
searchRoot = searchRoot.left;
} else {
searchRoot = searchRoot.right;
}
}
}
}
return match;
}
public void insert(T value) {
this.root = insert(this.root, value);
}
private Node<T> insert(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
if (value.compareTo(node.value) <= 0) {
node.left = insert(node.left, value);
} else {
node.right = insert(node.right, value);
}
}
return node;
}
public void insertNonRecursively(T value) {
this.root = insertNonRecursively(this.root, value);
}
private Node<T> insertNonRecursively(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
Node<T> runner = node;
boolean inserted = false;
while (!inserted) {
if (value.compareTo(runner.value) < 0) {
if (runner.left == null) {
runner.left = new Node<T>(value);
inserted = true;
} else {
runner = runner.left;
}
} else {
if (runner.right == null) {
runner.right = new Node<T>(value);
inserted = true;
} else {
runner = runner.right;
}
}
}
}
return node;
}
public static class Node<T extends Comparable<T>> {
private Node<T> left;
private Node<T> right;
private T value;
public Node(T value) {
this.left = null;
this.right = null;
this.value = value;
}
public Node<T> getLeft() {
return left;
}
public Node<T> getRight() {
return right;
}
public T getValue() {
return value;
}
}
}
Make your Binary Tree generic like
public class BinaryTree<T extends Comparable<T>>{
...
}
Whenever creating a BinaryTree instance, specify the containied type:
new BinaryTree<MyClass>();
Where MyClass must implement Comparable<MyClass>, i.e. be comparable to Objects of the same class.
Your methods would read as (example):
public Node lookup(T value) { ... }
The same applies for your Node class. Make it generic the same way.
I am learning algorithms myself, and I tried to implement LinkedList in Java with generic types from scratch. I had a version with Object which works well, but when I updated it with generic types, it gives warnings. Can anybody help where does the "unchecked or unsafe operations" come from?
class LinkedListGeneric <T> {
private Node<T> head;
private int size;
public LinkedListGeneric() {
head = null;
size = 0;
}
public int size() {
return size;
}
public void add (T data) {
if (head == null) {
head = new Node<T> (data);
size = 1;
}
else {
Node<T> temp = new Node<T> (data);
search(size).setNext(temp);
size++;
}
}
public void add (T data, int position) {
if (position > size + 1 || position <= 0) {
System.out.println ("error.");
return;
}
Node<T> temp = new Node<T> (data);
if (position == 1) {
temp.setNext(head);
head = temp;
return;
}
Node<T> prev = search(position - 1);
temp.setNext(prev.getNext());
prev.setNext(temp);
}
public void delete (int position) {
if (position > size || position <= 0) {
System.out.println ("error.");
return;
}
if (position == 1) {
size--;
head = head.getNext();
return;
}
Node<T> prev = search(position - 1);
prev.setNext(prev.getNext().getNext());
size--;
}
public T getValue (int position) {
if (position > size || position <= 0) {
System.out.println ("error.");
return null;
}
Node<T> temp = search(position);
return temp.getData();
//return search(position).getData();
}
public int searchData(T data) {
Node<T> temp = head;
int position = 1;
boolean flag = false;
while (temp != null) {
if (temp.getData() == data) {
flag = true;
break;
}
else {
temp = temp.getNext();
position++;
}
}
if (flag) return position;
else return -1;
}
public void print() {
Node<T> temp = head;
int position = 1;
while (temp != null) {
System.out.println("Node " + position + ": " + temp.getData());
temp = temp.getNext();
position++;
}
}
private Node<T> search (int position) {
Node temp = head;
while (position > 0) {
temp = temp.getNext();
}
return temp;
}
private class Node<T> {
private T data;
private Node<T> next;
public Node() {
this.data = null;
next = null;
}
public Node(T data) {
this.data = data;
next = null;
}
public T getData() {
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}
The problem I see is your Node.getNext call is returning a Node instead of a Node<T>. This is equivalent to the method returning Node<Object> instead of the generic type.
So, you should change:
public Node getNext() {
return next;
}
to
public Node<T> getNext() {
return next;
}
Although sbochin's answer will fix some of your warnings, doing the following will fix all of them:
Replace all instances of T within your Node class, including the one in the class declaration, with T2.
Change the return of getNext to Node<T2>
Change the argument type in setNext to Node<T2>.
Change the type of temp in search to Node<T>.
You might also want to add an #SuppressWarnings("unused") to public Node() since that also generates a compiler warning.
You might also want to make your Node class a static class as none of it's methods depend on the LinkedListGeneric<T> object it is in.
Completely alternatively, you could just get rid of the type parameter from Node, which gets rid of all your warnings except the unused warning. You'd have to keep your class nonstatic however.
How would I go about writing an iterator to iterate over each value of a binary tree in "in-order" fashion? I should be using a stack. BinaryNode is a simple node class with pointers to "left" and "right" nodes. Here is what I have so far:
class InOrderIterator implements Iterator<T> {
private Stack<BinaryNode> stack;
public InOrderIterator(BinarySearchTree<T>.BinaryNode root) {
stack = new Stack<BinaryNode>();
stack.push(root);
}
#Override
public boolean hasNext() {
while (!this.stack.isEmpty() && stack.peek() == NULL_NODE)
this.stack.pop();
return !this.stack.isEmpty();
}
#Override
public T next() {
//TODO
if (!this.hasNext())
throw new NoSuchElementException("No more nodes in tree!");
BinaryNode current = this.stack.pop();
BinaryNode output = null;
while(current != NULL_NODE){
this.stack.push(current);
current = current.left;
}
if(current == NULL_NODE){
if(!this.stack.isEmpty()){
output = this.stack.pop();
return output.data;
}
}
return null;
}
}
I have the basic algorithm down, but I can't seem to convert it to java code.
Think about invariants. You have a stack of nodes. What does it mean for a node to be on the stack?
Might I suggest: A node on the stack represents a "half-tree", a node and its entire right subtree, and the stack holds all the half-trees that together make up all the nodes that have not been returned from next() yet.
In what order should those half-trees be pushed on the stack? Answering that question gives you your invariant condition, the property that will be preserved as your code runs.
Satisfy yourself that your invariant implies that the top of the stack must be whatever next() is going to return next. When you pop it off to return it, you're going to have to somehow deal with its right subtree before returning. From your invariant, it should be obvious how to do that.
If you don't consciously and explicitly think about what your variables mean and what your invariants are, your coding efforts are going to be undirected. You're going to flail around, writing spaghetti code. Once you've done that, though, the code will write itself.
public class BinaryTreeNode {
private int element; //element stored at this node
private BinaryTreeNode left, right;
public BinaryTreeNode() { }
public BinaryTreeNode(int element) {
setElement(element);
setLeft(null);
setRight(null);
}
//returns the elements stored at this position
public int element() {
return element;
}
//sets the elements stored at this position
public void setElement(int e) {
element = e;
}
//return the left child of this position
public BinaryTreeNode getLeft() {
return left;
}
//set the left chid of this position
public void setLeft(BinaryTreeNode l) {
left = l;
}
//return the right child of this position
public BinaryTreeNode getRight() {
return right;
}
//sets the right child of this position
public void setRight(BinaryTreeNode r) {
right = r;
}
}
public class TestBTN {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
BinaryTreeNode root = null, right, left, node = null;
int arrayInt[] = {25, 20, 7, 13, 33, 50, 45, 17, 30, 55};
for (int i = 0; i < arrayInt.length; i++) {
if (root == null) {
root = node = new BinaryTreeNode(arrayInt[0]);
}//endIf
else {
node = new BinaryTreeNode(arrayInt[i]);
BinaryTreeNode s, p;
p = s = root;
while (s != null) {
p = s;
if (node.element() > s.element()) {
s = s.getRight();
} else {
s = s.getLeft();
}
}//endWhile
if (node.element() > p.element()) {
p.setRight(node);
} else {
p.setLeft(node);
}
}//emdElse
}//endFor
//printing
//Print(root);
//PostOrder(root);
//PreOrder(root);
InOrder(root);
//System.out.println("\nBinaryTreeNode");
}//endMain
private static void Print(BinaryTreeNode node) {
if (node != null) {
System.out.print(node.element() + " ");
Print(node.getLeft());
Print(node.getRight());
}//endIf
}//endPrint
static void PostOrder(BinaryTreeNode ptr) {
if(ptr != null) {
PostOrder(ptr.getLeft());
PostOrder(ptr.getRight());
System.out.print(ptr.element()+" ");
}//endIf
}//endPost
static void PreOrder(BinaryTreeNode ptr) {
if(ptr != null) {
System.out.print(ptr.element()+" ");
PreOrder(ptr.getLeft());
PreOrder(ptr.getRight());
}
}
static void InOrder(BinaryTreeNode ptr) {
if(ptr != null) {
InOrder(ptr.getLeft());
System.out.print(ptr.element()+" ");
InOrder(ptr.getRight());
}
}
}
I am trying to create null nodes at the bottom of a RBTree and want to instantiate EMPTY as an empty node.
this the line that has the error:
final private Node<E> EMPTY = new Empty();
And the empty class:
private class Empty extends Node<E> {
public Empty() {
red = false;
}
public Node<E> add(E data) {
count++;
return new Node<E>(data);
}
public Node<E> getNode(E data) {
return null;
}
}
I know it has something to do with the constructor but I can't zero in on it.
I have tried searching but most everything I come across on this site is related to android programming and/or some other language I'm not familiar with. I've tried the following:
(Node) casting the new Empty(); then realized it was obviously not that.
and working with the class seeing if public would work.
Aside from programming changes i've also tried the solutions offered here:
http://philip.yurchuk.com/software/eclipse-cannot-be-resolved-to-a-type-error/
But to no success.
Sorry if this question is out of place, and thank you for your time!
complete code:
package data_structures;
public class RedBlackTree<E extends Comparable<E>> {
private Node<E> root;
private int count = 0;
final private Node<E> EMPTY = new Empty<E>();
public RedBlackTree() {
root = EMPTY;
}
public void add(E data) {
root = root.add(data);
count++;
root.red = false;
}
public boolean find(E data) {
return root.getNode(data) != null;
}
private class Node<E> {
public E data;
public boolean red;
public Node<E> leftChild;
public Node<E> rightChild;
/** Used by Empty */
protected Node() {
assert EMPTY == null;
}
/** Nodes always begin red */
public Node(E k) {
data = k;
red = true;
leftChild = (Node<E>) EMPTY;
rightChild = (Node<E>) EMPTY;
}
private boolean isRed() {
return red;
}
public int height(){
return 0; //returns the counts binary left most bit position to determine the height.
}
public Node<E> add(E newData) {
if(((Comparable<E>) newData).compareTo(data) == -1) {
count++;
leftChild = leftChild.add(newData);
return leftChild;
}
if(((Comparable<E>) newData).compareTo(data) == +1){
count++;
rightChild = rightChild.add(newData);
return rightChild;
}
if(((Comparable<E>) newData).compareTo(data) == 0){
return this;
}
if (leftChild.isRed() && leftChild.leftChild.isRed()) {
return balance(leftChild.leftChild, leftChild, this,
leftChild.leftChild.rightChild, leftChild.rightChild);
} else if (leftChild.isRed() && leftChild.rightChild.isRed()) {
return balance(leftChild, leftChild.rightChild, this,
leftChild.rightChild.leftChild, leftChild.rightChild.rightChild);
} else if (rightChild.isRed() && rightChild.leftChild.isRed()) {
return balance(this, rightChild.leftChild, rightChild,
rightChild.leftChild.leftChild, rightChild.leftChild.rightChild);
} else if (rightChild.isRed() && rightChild.rightChild.isRed()) {
return balance(this, rightChild, rightChild.rightChild,
rightChild.leftChild, rightChild.rightChild.leftChild);
}
return this;
}
/** Returns the node for this key, or null. */
public Node<E> getNode(E newData) {
if(((Comparable<E>) newData).compareTo(data) == -1){
return leftChild.getNode(newData);
}
if(((Comparable<E>) newData).compareTo(data) == +1){
return rightChild.getNode(newData);
}
else{
return this;
}
}
private class Empty<E> extends Node<E> {
public Empty() {
red = false;
}
public Node<E> add(E data) {
count++;
return new Node<E>(data);
}
public Node<E> getNode(E data) {
return null;
}
}
private Node<E> balance(Node<E> a, Node<E> b, Node<E> c, Node<E> d, Node<E> e) {
a.rightChild = d;
b.leftChild = a;
b.rightChild = c;
c.leftChild = e;
a.red = false;
b.red = true;
c.red = false;
return b;
}
}
}
You can't write
Node<E> EMPTY = new Empty<E>();
because E is a generic type. You can only create an object with actual class, such as:
Node<String> EMPTY = new Empty<String>()
If you know what you are doing, you can do an ugly trick that should work with a warning
Node<E> EMPTY = new Empty();
Also, move the Empty class outside of Node.