Iterative approach to BST - java

these are my fields:
public class BSTSet <E> extends AbstractSet <E> {
// Data fields
private BSTNode root;
private int count = 0;
private Comparator<E> comp; // default comparator
/** Private class for the nodes.
* Has public fields so methods in BSTSet can access fields directly.
*/
private class BSTNode {
// Data fields
public E value;
public BSTNode left = null;
public BSTNode right = null;
// Constructor
public BSTNode(E v) {
value = v;
}
//creates a method called contains so that i can call it later on for my find method
public boolean contains(Object item) {
return contains(item);//root.value.equals(item);
}
public int height() {
return height();
}
}
// Constructors - can either use a default comparator or provide one
public BSTSet() {
comp = new ComparableComparator(); // Declared below
}
public BSTSet(Comparator <E> c) {
comp = c;
}
}
and this is what i am trying to complete:
private class BSTSetIterator implements Iterator<E> {
private Stack<BSTNode> stack = new Stack<BSTNode>();
private BSTNode current = root;
public BSTSetIterator(BSTNode root) {
return new BSTSetIterator();
}
public boolean hasNext() {
boolean hasNext = false;
hasNext = !stack.isEmpty() || current != null;
return hasNext;
}
public E next() {
BSTNode next = null;
while (current != null) {
stack.push(current);
current = current.left;
}
next = stack.pop();
current = next.right;
return next;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
// Comparator for comparable
private class ComparableComparator implements Comparator<E> {
public int compare(E ob1, E ob2) {
return ((Comparable)ob1).compareTo(ob2);
}
}
So far the code fails at lines return new BSTSetIterator(); and return next;. For return next it says that it is the wrong data type to return. How would I go about fixing these methods so that I can iterate through a BST using a Stack?

BSTSetIterator();
This doesn't work, because your constructor expects a root and you didn't pass that parameter. If you have a BSTSet object called 'tree', and you want to create a new iterator, then you should create the iterator this way:
BSTSetIterator iterator = new BSTSetIterator(tree.getRoot());
However, you don't have a getter in your BSTSet class and your root is private. Don't worry, the solution for that problem is to create a public getter inside your BSTSetIterator class, like this:
public BSTNode getRoot()
{
return this.root;
}
Constructors don't return values, this is incorrect:
public BSTSetIterator(BSTNode root) {
return new BSTSetIterator();
}
Instead, write your construtor this way:
public BSTSetIterator(BSTNode root)
{
this.current = root;
}
Also, this definition is incorrect, because root is out of reach:
private BSTNode current = root;
You should have this instead:
private BSTNode current;
As for your other problem,
BSTNode next = null;
means that your variable called 'next' is of BSTNode type.
public E next()
means that your method called next is of E type. as E and BSTNode is not the same, your return:
return next;
is incorrect. I could give you more help, but I have realized you are learning now the language and it's better to let you explore yourself the technology and programming in general, because this way you will become quicker. "Give a man a fish, and you feed him for a day. Teach a man how to fish, and you feed him for a lifetime."

Related

Adding nodes to a list in ascending order with Java

Is there a way to use the compareTo function when comparing objects, I'm not sure if it's just for Strings. I am trying add an node into its correct position in ascending order.
heres where I declare my attributes/constructor
private Node<E> head; //refers to the head of the node
private int size; // keeps track of the size of the list
// default constructor which creates empty ordered list
public OrderedList(){head = null; size = 0;}
Heres my insert function
public void insert(Object o)
{
Node n = new Node(o, null); // creates new node
// Node for first element greater than or equal
Node current = head.getLink();
Node before = head; // Node for right before the next one is found
// checks to see if list is empty
if(size == 0)
{
head = n;
}
// checks if element is smaller than the head
else if (o.compareTo(head.o) < 0)
{
n.getLink() = head;
head = n;
}
}
here is my node class
package project.pkg3;
public class Node<T>
{
private Object data;
private Node link;
public Node(Object o, Node l){data = o; link = l;}
public void setData(Object o){data = o;}
public void setLink(Node l){link = l;}
public Object getData(){return data;}
public Node getLink(){return link;}
}
I'm getting an error message when trying to check whether the element belongs in the front on this line
else if (o.compareTo(head.o) < 0)
telling me that it cannot find the symbol, which I'm not sure what that means
Im also getting another error message on this line
n.getLink() = head;
this one is telling me that it's an unexpected type
If your linked list must be sorted using compareTo(), then you need to make sure that the underlying data is comparable.
public class Node<T extends Comparable>
{
private T data;
private Node<T> link;
public Node(T o, Node<T> l) { data = o; link = l; }
public void setData(T o) { data = o; }
public void setLink(Node<T> l) {link = l; }
public T getData() { return data; }
public Node<T> getLink() { return link; }
}
Then this block
else if (o.compareTo(head.o) < 0)
{
n.getLink() = head;
head = n;
}
should be changed into this:
else if (
(o.getData() != null) ?
(o.getData().compareTo(head.getData()) < 0) :
(head.getData().compareTo(o.getData()) > 0)
)
{
n.setLink(head);
head = n;
}
I didn't look at your linked list implementation though, so I have no idea the other stuff are correct.
Your node class should implement java.lang.Comparable interface and override its compareTo() method as per your logic.
public class Node<T extends Comparable<T>>{
}
Your argument object would implement Comparable interface. For eg:
public class Name implements Comparable<Name> {
private String str1;
public int compareTo(Name o) {
//your logic here to compare object with itself
return this.str1.compareTo(o.str1);
}
}

Implementation of a Generic BST

Hello I would like to know how to set up an object oriented BST class that has a private Node class.(Both classes being generic)
so far I have this but i am having some compilation errors. Some explanation would be nice. I copied this code, but I know there are mistakes to fix. Also how would you set up the constructor of the bst?
#SuppressWarnings("unchecked")
//public class BinarySearchTree<T extends Comparable<? super T>> {
public class BST<T extends Comparable<T>> implements Iterable<T>
{
private Node <T> root;
// public BST(){
// root=null;
// }
private T search(T target, BST <T> p)
{
int comp=target.compareTo(p.data);
T c=target.compareTo(P.data);
if(comp==0)
return c;
}
private class Node<T extends Comparable<T>> implements Iterable {
T data;
Node<T> left, right;
public Node(T t)
{
data=t;
}
#Override
public Iterator iterator() {
// TODO Auto-generated method stub
return null;
}
public T search(T target)
{
return search(target, root);
}
}
#Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return null;
}
}
The default constructor should be fine that you've originally commented out should be fine. Is there a particular use case you have in mind that it doesn't satisfy?
Something like this. Because the Node class is a private inner class, it doesn't have to be generic and can instead use the type specified in its parent class, which is what I assume you want anyway.
The node class doesn't really need a search method because it only contains one value. There's no need to search if there's just one value. This is also the same reason it doesn't need a iterator either. There's really no need to iterate over just one value.
When designing an abstract data type such as a BST, it's good to consider how you envision it will be used: what operations should it support, aka. its API. The implementation below supports 2 operations: insert and search. Possible extensions might include a remove and/or a contains operation.
Operations on a tree are typically recursive. This is because you start at the root and have to traverse through inner nodes which themselves can be viewed as roots of their respective subtrees. Try walking through a few example inserts and searches to convince yourself why it works that way.
import java.util.Iterator;
public class BST<T extends Comparable<T>> implements Iterable<T> {
private Node root;
public BST(){
root=null;
}
private void insertInternal(T value, Node parent) {
int comp=value.compareTo(parent.data);
if(comp < 0) {
if(parent.left == null) {
parent.left = new Node(value);
}
else {
insertInternal(value, parent.left);
}
}
else if(comp > 0) {
if(parent.right == null) {
parent.right = new Node(value);
}
else {
insertInternal(value, parent.right);
}
}
}
public void insert(T value) {
if(root == null) {
root = new Node(value);
return;
}
insertInternal(value, root);
}
private Node searchInternal(T target, Node node) {
if(node == null) {
return null;
}
int comp=target.compareTo(node.data);
if(comp < 0) {
return searchInternal(target, node.left);
}
else if(comp > 0) {
return searchInternal(target, node.right);
}
return node;
}
public Node search(T target) {
return searchInternal(target, root);
}
private class Node {
T data;
Node left, right;
public Node(T t) {
data=t;
}
}
#Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return null;
}
public static void main(String[] args) {
BST<Integer> bst = new BST<Integer>();
bst.insert(2);
bst.insert(6);
System.out.println(bst.search(2) != null);
System.out.println(bst.search(6) != null);
System.out.println(bst.search(8) == null);
}
}

Binary Search Tree Cloning - Java

It's a homework problem. we need to build a method in java that clones a given binary search tree through recursion, ive looked up several examples online, the problem being that the program our instructor asked us to write was in what he called the Modern method, whereby rather than checking for null in each method, a tree is constructed using Dynamic dispatch from an Interface Node, connected to two subclasses nil(representing an empty node and the necessary methods to deal with an instance of an empty Node) and Vertex, a filled node and its affiliate methods. im confused on how to structure the recursion to clone the nodes, and construct the nodes to hold the cloned info. this being homework im obviously not looking for an answer but i really need some help with this.
interface Node<T extends Comparable<T>>
{
public int size();//return the number of values in the tree
public boolean empty();//true if tree is empty nil
public Node<T> insert(T x);// insert something into a binary search tree, return the node it was inserted into
public vertex<T> search(T x);//search for a given value and return the vertex ( filled node ) it exists in
public int depth();//returns the greatest depth of the tree
public void inorder();
//public Node<T> Attack_of_the_clones();
}
//note that insert must be used as in t = t.insert(x)
class nil<T extends Comparable<T>> implements Node<T> //empty tree
{
public int size() {return 0;}// empty node, therefore of size zero
public boolean empty() { return true; }//its and empty node, duh
public Node<T> insert(T x) { return new vertex<T>(x); }// returns a Tpe Node for inserting a given value into a node (thereby creating a
//vertex containing said inserted value)
public vertex<T> search (T x) { return null; }//RETURNS NULL IN SEARCHING FOR A GIVE VALUE BECAUSE NODES OF TPE nIL ARE INHERENTLY empty
public int depth() { return 0; }
public void inorder() { System.out.print("0");}
//public Node<T> Attack_of_the_clones() { return new nil<T>(this); }
}//end nil
class vertex<T extends Comparable<T>> implements Node<T>
{
protected T head;// the root of the tree
protected Node<T> left;//creates an instance of Node to serve as the left child of head
protected Node<T> right;
//constructor
public vertex(T h, Node<T> l, Node<T> r) { head = h; left = l; right = r; }// a constructed instance
//leaf instructor
public vertex(T h) { head = h; left = new nil<T>(); right = new nil<T>(); }//a constructed leaf
// a leaf is Tpically a node with no or null children, some consider the null nodes themselves to be leaves
//accesors so that the protected variables can be displayed
public T acHead() {return head;}
public Node<T> acLeft() {return left;}
public Node<T> acRight() {return right;}
public int size()
{
return left.size() + right.size() + 1;//recursively call size down the left and right trees to get all the nodes,
// and combine them ( +1 for the root) to get the size of the tree
}
public int depth()
{
return Math.max((left.depth()+1),(right.depth()+1));
}
public boolean empty() {return false; }//because its of class vertex and therefore not empty
public Node<T> insert(T x)
{
if (x.compareTo(head) <= 0)// go down left tree
left = left.insert(x);
else right = right.insert(x);// go right
return this;//root vertex has not changed
}//end insert
public vertex<T> search(T x)
{
int r = x.compareTo(head);
if(r==0)//go left
{
return left.search(x);//recursively call search using said node to move down tree
}
else //go right
{
return right.search(x);
}
}// end binary search
public void inorder()
{
Node<T> current_root = this;
if(current_root == null)
return;
left.inorder();
System.out.println(current_root + ", ");
right.inorder();
}//end inorder print
/*public Node<T> Attack_of_the_clones()
{
left_copy = curr_node.left.copy();
right_copy = curr_node.right.copy();
return new vertex(curr_node, left1, right1);
}*/
public vertex<T> largest(Node<T> x)
{
int left1 = largest(x.left);
int right1 = right.largest();
if(this.head > left1 && this.head > right1)
return this.root;
else
return Math.max(left1,right1);
}
}// end vertex
public class BinaryTree
{
public static void main(String[] args)
{
Node<Integer> n = new vertex<Integer>(3);
n = n.insert(4);
for(int i = 0; i < 10; i++)
{
n.insert((int)Math.random*8);
}
n.size();
n.depth();
n.inorder();
}//end main
}//end Binary Tree
BinaryTree.java:87: warning: [rawtypes] found raw type: vertex
public Node<T> Attack_of_the_clones() { return new vertex(head, left.Attack_of_the_clones(), right.Attack_of_the_clones());}
^
missing type arguments for generic class vertex<T>
where T is a type-variable:
T extends Comparable<T> declared in class vertex
BinaryTree.java:87: warning: [unchecked] unchecked call to vertex(T,Node<T>,Node<T>) as a member of the raw type vertex
public Node<T> Attack_of_the_clones() { return new vertex(head, left.Attack_of_the_clones(), right.Attack_of_the_clones());}
^
where T is a type-variable:
T extends Comparable<T> declared in class vertex
BinaryTree.java:87: warning: [unchecked] unchecked conversion
public Node<T> Attack_of_the_clones() { return new vertex(head, left.Attack_of_the_clones(), right.Attack_of_the_clones());}
^
required: Node<T>
found: vertex
where T is a type-variable:
T extends Comparable<T> declared in class vertex
3 warnings
As Nil has no fields (is immutable) then its clone can just return itself.
//On Nil
public Node<T> myClone(){
return this;
}
On Vertex you want to do a deep clone (cloning the fields instead of just copying their references).
//On Vertex
public Node<T> myClone(){
return new Vertex<T>(head,left.myClone(),right.myClone())
}

find method for BST still not working

These are my fields:
public class BSTSet <E> extends AbstractSet <E> {
// Data fields
private BSTNode root;
private int count = 0;
private Comparator<E> comp; // default comparator
/** Private class for the nodes.
* Has public fields so methods in BSTSet can access fields directly.
*/
private class BSTNode {
// Data fields
public E value;
public BSTNode left = null;
public BSTNode right = null;
// Constructor
public BSTNode(E v) {
value = v;
}
}
// Constructors - can either use a default comparator or provide one
public BSTSet() {
comp = new ComparableComparator(); // Declared below
}
public BSTSet(Comparator <E> c) {
comp = c;
}
// Methods
/** Return true iff the set is empty */
public boolean isEmpty() {
return count == 0;
}
/** Return the number of elements in set */
public int size() {
return count;
}
and this is the method i am trying to fix:
/** Return true iff (if and only if) the set contains an item
* (the item must be non null)
*/
public boolean contains(Object item) {
// YOUR CODE HERE
//changes item to E so it can be used in the comparator
E value1 = (E) item;
if (root.value.equals(item)){
return true;
}
int s = comp.compare(value1,root.value);
if(s<0){
if (root.left == null)
return false;
else
return root.left.contains(item);
}
else if(s>0){
if (root.right == null)
return false;
else
return root.right.contains(item);
}
}
so far everything seems to go okay, but it fails at return root.left.contains(item); and says it cannot find symbol - method contains. How do i fix this so that i can run my contains method which should return whether or not the value is in the BST?
Both left and right are declared as BSTNode instances. BSTNode doesn't have a method called contains, so you need to add one:
public boolean contains(Object item) {
return value.equals(item);
}
Ideally, you'd want both your nodes and sets to implement the same interface, so you don't know which implementation you're actually calling.

Compile error with Java generic types

I'm doing a learning exercise and creating my own linked list with an iterator. The class is as follows:
public class LinkedList<T> implements Iterable <T> {
private Node<T> head;
private Node<T> tail;
private int size;
public LinkedList() {
head = new Node<T>();
tail = new Node<T>();
head.setNext(tail);
tail.setPrevious(head);
size = 0;
}
public void append(T element) {
tail.getPrevious().setNext(new Node<T>(element));
tail.getPrevious().getNext().setNext(tail);
tail.getPrevious().getNext().setPrevious(tail.getPrevious());
tail.setPrevious(tail.getPrevious().getNext());
size++;
}
public void prepend(T element) {
head.getNext().setPrevious(new Node<T>(element));
head.getNext().getPrevious().setPrevious(head);
head.getNext().getPrevious().setNext(head.getNext());
head.setNext(head.getNext().getPrevious());
size++;
}
public void remove(Node<T> nodeToRemove) {
if(!isEmpty()) {
nodeToRemove.getPrevious().setNext(nodeToRemove.getNext());
nodeToRemove.getNext().setPrevious(nodeToRemove.getPrevious());
nodeToRemove.setNext(null);
nodeToRemove.setPrevious(null);
nodeToRemove.setElement(null);
nodeToRemove = null;
size--;
}
}
public boolean isEmpty() {
return size() == 0;
}
public int size() {
return size;
}
public Iterator<T> iterator() {
return new Cursor<T>(head);
}
public String toString() {
String result = "";
for(T t : this) {
result += t.toString() + "\n";
}
return result;
}
private final class Cursor<E> implements Iterator<E> {
private Node<E> current;
public <E> Cursor(Node<E> head) {
this.current = current;
}
public boolean hasNext() {
return current.getNext().getNext() != null;
}
public E next() {
current = current.getNext();
return current.getElement();
}
public void remove() {
remove(current);
}
}
}
After doing quite a bit of research it appears a good way to implement the iterator is to do it as an innner class. However, I'm getting a compile error with my remove method in the cursor class. I believe it's because of a type mismatch although the error I'm getting is remove() in LinkedList<T>.Cursor<E> cannot be applied to <Node<E>).
I've wrestled with this for quite some time and I can't understand what is wrong exactly, I would appreciate any insights you may have.
There are a few things wrong:
You have 2 methods called remove. Java thinks you are trying to call remove in the inner Cursor class which takes no parameters. You have to qualify the reference like this:
LinkedList.this.remove(current);
Your inner cursor class is non-static. Non-static inner classes are associated with the outer class instance that created them. Basically, they maintain a parent pointer to the outer class object. This is correct for implementing an iterator, but you need to change how you're using generics. Non-static inner classes can use the type parameters of their parent class. This means you can change your iterator definition to:
private final class Cursor implements Iterator<T>
and it will automatically use the <T> from LinkedList.
this.current = current; should probably be this.current = head;
Why does hasNext call getNext() twice?
Hope that helps.

Categories

Resources