I do have a hw question...I have to write a remove method for a binary search tree, so far what I have is below but I keep getting a bunch of errors associated with my remove method and I'm not sure why...would someone please be able to check my code. Thank You. I also tried to create a find method but I'm having some trouble with that as well...that is all the way at the bottom of my remove code.
import java.util.*;
class TreeNode383<E extends Comparable> {
private E data;
private TreeNode383<E> left;
private TreeNode383<E> right;
private TreeNode383<E> parent;
public TreeNode383( ) { left = right = parent = null; }
public TreeNode383( E d, TreeNode383 <E> l, TreeNode383 <E> r,
TreeNode383 <E> p) {
data = d;
left = l;
right = r;
parent = p;
}
public E getData( ) { return data; }
public void setData(E d) { data = d; }
public TreeNode383<E> getLeft( ) { return left; }
public void setLeft(TreeNode383<E> l) { left = l; }
public TreeNode383<E> getRight( ) { return right; }
public void setRight(TreeNode383<E> r) { right = r; }
public TreeNode383<E> getParent( ) { return parent; }
public void setParent(TreeNode383<E> p) { parent = p; }
public String toString( ) {
String answer = "";
if (left != null) answer += left.toString( );
answer += data + " ";
if (right != null) answer += right.toString( );
return answer;
}
}
**The start of my remove method**
boolean remove (E obj)
{
if(root == obj)
return false;
//when deleting a leaf just delete it
else if(obj.getleft == NULL && obj.getright == NULL)
parent = obj = NULL;
//when deleting an interior node with 1 child
//replace that node with the child
else if(obj.getleft == NULL && obj.getright != NULL)
obj.setright = new TreeNode383<E>(newData, null, null, null);
else if(obj.getleft != NULL && obj.getright == NULL
obj.setleft = new TreeNode383<E>(newData, null, null, null);
//when deleting an interior node with 2 children
//find left most node in right subtree,
//promote it to replace the deleted node
//promote its child to replace where it was
/*
private BinaryNode findMin( BinaryNode t )
{
if( t == null )
return null;
else if( t.left == null )
return t;
return findMin( t.left );
}
*/
obj is an instance of E not TreeNode383<E> so it has no getLeft() or getRight() method. And even if it did, you spelled it wrong.
And what's root? I can't see a declaration for that anywhere.
This syntax makes no sense either:
obj.setright = new TreeNode383<E>(newData, null, null, null);
setRight() is a method not a field (Java does not have properties like C#) Plus you need a capital 'R' in the name.
So maybe that should be
obj.setRight(new TreeNode383<E>(newData, null, null, null));
that is, if newData was declared, which it isn't.
There are too many errors here to make sense of your code. Try implementing one function at a time.
ya..there are some errors...basically, to remove a node N from a BST, replace N with the minimum element in the right subtree of N.
Related
This is my first time running the debugger to check the values of my binary search tree but it seems to skip through all the debugger and it has a weird arrow beside the blue dot. By the way, the skip all breakpoints is disabled I made sure of it.
This is a short GIF of me running the program
https://gyazo.com/e236c1bd75ac746bf9982871ca847233
Added my other class
public class BinaryTree<T extends Comparable<T>> {
private class Node{
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 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 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;
}
private void removeInner( T data, Node node ) {
Node temp;
while ( node.data!=data) {
int compare = data.compareTo(node.data);
if ( compare < 1 ){
node = node.left;
}
// make node.left if it is filled
if ( compare > 1 ){
node = node.right;
}
if ( compare == 0) {
node = null;
}
}
}
}
You have one or more so-called Trigger Points (decorated with a T) somewhere else from which one must be hit first to activate the other regular breakpoints. This can be seen by the regular breakpoint in line 9 being decorated with a crossed-out T.
Solution: Delete or deactivate all Trigger Points (those decorated with T), e.g. in the Breakpoints view.
I am attempting to use recursion to search through a binary tree and return true or false depending on if the binary tree contains the string. Here is my code
public class BinaryTree {
private String data;
private BinaryTree leftChild;
private BinaryTree rightChild;
public BinaryTree() {
data = null;
leftChild = null;
rightChild = null;
}
public BinaryTree(String d) {
data = d;
leftChild = new BinaryTree();
rightChild = new BinaryTree();
}
// This constructor is unchanged
public BinaryTree(String d, BinaryTree left, BinaryTree right) {
data = d;
leftChild = left;
rightChild = right;
}
// Get methods
public String getData() {
return data;
}
public BinaryTree getLeftChild() {
return leftChild;
}
public BinaryTree getRightChild() {
return rightChild;
}
// Set methods
public void setData(String d) {
data = d;
}
public void setLeftChild(BinaryTree left) {
leftChild = left;
}
public void setRightChild(BinaryTree right) {
rightChild = right;
}
public boolean contains(String d) {
return d != null && (this.getData().equals(d) ||
contains(this.getLeftChild().getData()) ||
contains(this.getRightChild().getData()));
}
So, my issue is with the contains method as it keeps giving me a stackoverflow.error . I was hoping i could get assistance on this thanks in advance.
You could try this:
public boolean contains(String d)
{
// Not contained if specified string is null
if (d == null)
return (false);
// OK if specified string equals our data
if ((data != null) && data.equals(d))
return (true);
// OK if contained in left tree
if ((leftChild != null) && leftChild.contains(d))
return (true);
// OK if contained in right tree
if ((rightChild != null) && rightChild.contains(d))
return (true);
// Otherwise, it's not OK
return (false);
} // contains
What you're doing there is not recursion. You are asking:
boolean found = tree.contains(candidate)
right?
Your code expands this to
boolean found = candidate != null && (tree.getData.equals(d) || LEFT || RIGHT)
where LEFT is
contains(tree.getLeftChild().getData())
which is not comparing the candidate string with the left data at all but rather expands to
candidate != null && (tree.getData.equals(candidate) || LEFT || RIGHT)
which results in an endless loop, causing the StackOverflow.
You should reformulate the class as
public class Node {
Node left, right;
String data
public boolean contains(String d);
}
and then your tree would be a root Node and the search could be recursive.
On each recursive call this refers to the same object and hence you keep on passing the same values over and over again. You need to pass BinaryTree references as a parameter.
private boolean contains(String data, BinaryTree node) {
if (node == null) {
return false;
}
return node.getData().equals(data) || contains(data, node.getLeftChild())
|| contains(data, node.getRightChild());
}
The main (public) contains needs to pass the String to be searched and the root to the above method.
I'm struggling to understand why this class is not functioning. It was part of an assignment for a course on Data Structures(EDIT: The deadline for the assignment has passed, I just want to figure it out...). The node is part of an AVL tree built upon a BST and the way I chose to implement it is by creating methods within my Node class to find the Balance factor and height.
The class is structured as follows:
public class Node<T extends Comparable<? super T>> {
public T data;
public Node left;
public Node right;
public Node(T IN) {
data = IN;
}
public Node(T IN, Node L, Node R) {
this(IN);
left = L;
right = R;
}
#Override
public String toString() {
return data.toString();
}
#Override
public Node clone() {
return new Node(this.data) ;
}
public int getHeight() {
return getHeight(this) ;
}
public int getBF() {
//Calculate BF
int balanceFactor = 0;
if (right != null && left != null)
balanceFactor = getHeight(right) - getHeight(left);
else if (left != null) {
balanceFactor = 0 - getHeight(left) ;
}
else if (right != null) {
balanceFactor = getHeight(right) ;
}
else
balanceFactor = 0 ;
return balanceFactor ;
}
private int getHeight(Node p) {
if (p.left == null && p.right == null ) {
return 0 ;
}
else if (p.left != null && p.right != null) {
return 1 + max(p.left.getHeight(), p.right.getHeight());
}
else if (p.left != null) {
return 1 + p.left.getHeight() ;
}
else if (p.right != null) {
return 1 + p.right.getHeight() ;
}
else {
return 0;
}
}
private int max(int x, int y) {
if (x >= y) {
return x;
} else {
return y;
}
}
}
and the function calling the method is:
#Override
public boolean insert(T el) {
boolean test = super.insert(el) ;
if (test) {
return checkBalance(root) ;
}
else
return false ;
}
and the exception I recieve is a repetition of:
Exception in thread "main" java.lang.StackOverflowError
at Node.getHeight(Node.java:54)
at Node.getHeight(Node.java:33)
at Node.getHeight(Node.java:58)
I would suggest that either your tree is deformed or really big. There seems to be no problems with the code.
If your tree is deformed in such a way that you have a Node inserted twice in the same tree then this code will break.
Added - You are eating a little more stack than you need - replacing p.left.getHeight() with getHeight(p.left) etc. would avoid one stack push per recursion. If your issue is merely big tree then this might scrape you through but this would only postpone the problem.
From looking at both getHeight methods, it seems like you don't have a tree but a cyclic graph. You should start testing with a tree consisting of only the root and then add nodes until you observe the infinite recursion. You probably have an error in the function that rebalances the tree.
EDIT: And you should make the attributes (at least left and right) private.
NOTICE: this is homework-related, but I'm not tagging it as such because the 'homework' tag is marked as obselete (?)
Using the following class that implements a binary tree...
class TreeNode
{
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue)
{
value = initValue;
left = null;
right = null;
}
public TreeNode(Object initValue, TreeNode initLeft, TreeNode initRight)
{
value = initValue;
left = initLeft;
right = initRight;
}
public Object getValue()
{
return value;
}
public TreeNode getLeft()
{
return left;
}
public TreeNode getRight()
{
return right;
}
public void setValue(Object theNewValue)
{
value = theNewValue;
}
public void setLeft(TreeNode theNewLeft)
{
left = theNewLeft;
}
public void setRight(TreeNode theNewRight)
{
right = theNewRight;
}
}
I need to calculate the number of nodes in the binary tree that are "only children," this being defined as a node that doesn't have another node stemming from its parent.
This is what I have so far:
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if(isAnOnlyChild(t))
return 1;
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
I don't know how to implement the boolean method isAnOnlyChild(TreeNode t)
Could someone please help me?
You are pretty close and have the traversal looking good but in your Treenode you do not have a link between a child and its parent. So You can not tell from say a left child if a sibling (right child) exists.
You could have a parent Treenode (along with left and right) so you could check how many children a given node's parent has. Or as ajp15243 suggested, instead use a method that checks how many children a given node has.
Some pseudo code of the latter:
//we still need to check if that only child has its own children
if hasOnlyChild(t)
return 1 + checkOnlys(left) + checkOnlys(right)
else
return checkOnlys(left) + checkOnlys(right)
As you have already noticed, one solution is to count number of parents that have only one child. This should work:
public static int countOnlys(TreeNode t)
{
if(t == null || numberOfChildren(t)==0){
return 0;
}
if(numberOfChildren(t)==1){
return 1+ countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
if(numberOfChildren(t)==2 ){
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
return 0;
}
public static int numberOfChildren (TreeNode t){
int count = 0;
if(t.getLeft() != null ) count++;
if(t.getRight() != null) count++;
return count;
}
A parent has an only child if exactly one of the children is non-null (which implies that exactly one of its children is null):
((t.getLeft() == null || t.getRight() == null)) && !(t.getLeft() == null && t.getRight() == null)
You don't test, however, the node when you visit it as the recursive code traverses the tree. (This is similar to the Visitor pattern.) What you do is test for an only child when you are sitting on the parent. It's actually a logical exclusive-or test because one and only one of the children needs to be non-null to detect that this node has an only child.
So the algorithm is to
visit each node in the tree.
count it, if the node has only one child
That's it. The rest is plumbing.
public static int onlyChild(TreeNode t){
int res = 0;
if( t != null){
// ^ means XOR
if(t.getLeft() == null ^ t.getRight() == null){
res = 1;
}
res += onlyChild(t.getLeft()) + onlyChild(t.getRight()));
}
return res;
}
whenever you traverse a binary tree, think recursively. this should work.
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if (t.getLeft()==null&&t.getRight()==null)
return 1;
return countOnlys(t.getLeft())+countOnlys(t.getRight());
}
public int countNode(Node root) {
if(root == null)
return 0;
if(root.leftChild == null && root.rightChild == null)
return 0;
if(root.leftChild == null || root.rightChild == null)
return 1 + countNode(root.leftChild) + countNode(root.rightChild);
else
return countNode(root.leftChild) + countNode(root.rightChild);
}
So I've stumped on this current problem I'm working on. Basically, I need to add an element to my array based binary search tree. According to my text it is similar to the compareTo method. I'm not even sure what direction to head in. I'm a complete noob when it comes to OOP so any help would be appreciated.
package lab9;
public class BinarySearchTreeArray<E> {
Entry<E> [] tree;
Entry<E> root;
int size;
public BinarySearchTreeArray()
{
tree = null;
size = 0;
}
public int size()
{
return size;
}
public boolean contains(Object obj)
{
Entry<E> temp = root;
int comp;
if (obj == null)
throw new NullPointerException();
while (obj != null)
{
comp = ((Comparable)obj).compareTo (temp.element);
if (comp == 0)
return true;
else if (comp < 0)
temp = temp.left;
else
temp = temp.right;
}//while
return false;
}//contains method
/*
* From the text:
* The definition of the add (E element) method is only a little more
* complicated than the definition of contains (Object obj). Basically,
* the add method starts at the root and branches down the tree
* searching for the element; if the search fails, the element is
* inserted as a leaf.
*/
public void add(E e)
{
Entry<E> node = new Entry<E>(e);
if (tree[parent] == null)
{
tree[0] = node;
size++;
}
else
{
tree[1] = node;
size++;
}
}//add method
/****************************************************************/
protected static class Entry<E>
{
private E element;
private Entry<E> parent, left, right;
public Entry(E e){this.element = element; left = right = null;}
public Entry<E> getLeft(){return left;}
public Entry<E> getRight(){return right;}
}
/****************************************************************/
public static void main(String[] args) {
BinarySearchTreeArray<String> bsta1 = new BinarySearchTreeArray<String>();
BinarySearchTreeArray<Integer> bsta2 = new BinarySearchTreeArray<Integer>();
bsta1.add("dog");
bsta1.add("tutle");
bsta1.add("cat");
bsta1.add("ferrit");
bsta1.add("shark");
bsta1.add("whale");
bsta1.add("porpoise");
bsta2.add(3);
bsta2.add(18);
bsta2.add(4);
bsta2.add(99);
bsta2.add(50);
bsta2.add(23);
bsta2.add(5);
bsta2.add(101);
bsta2.add(77);
bsta2.add(87);
}
}
The add method is indeed similar to your contains method. In a typical binary tree represented with structs/objects you would access the right and left subtrees using pointers (as in your example temp.left and temp.right). But, since you have a tree in an array you need to access that array by index, so the question is : How to access the index that corresponds to the left/right subtrees?
For that, you can use the following expression left = parent * 2 and right = parent * 2 + 1. I will provide you with one example of the add method that would add elements to a tree represented as an array of integers, where -1 represents no values or null in java.
public void add(E e)
{
Entry<E> node = new Entry<E>(e);
index = 0;
int comp;
boolean not_add = true;
while(not_add)
{
if (tree[index] == null) //if this node is empty
{
tree[index] = node;
size++;
not_add = true;
}
comp = ((Comparable)e).compareTo (tree[index].element);
if(comp == 0) not_add = true; // Same value
else if (comp < 0) index = index * 2; // should be insert on the left
else index = index * 2 + 1; // should be insert on the right
}
}