Deletion function doing nothing - java

I am working on a Binary Search Tree for class and have most of my code implemented (I think) correctly, although if I attempt to delete the root node, nothing happens.
Does anyone see a problem with my code?
public class BinarySearchTree {
private Node root;
private int size = 0;
public BinarySearchTree(){
root = null;
}
public BinarySearchTree create(){
BinarySearchTree tree = new BinarySearchTree();
return tree;
}
public int size(){
return size;
}
public Node getRoot(){
System.out.println("root: " + root.getData());
return root;
}
public void insert(String s){
root = insertHelper(root, s.toLowerCase());
size++;
}
private Node insertHelper(Node n, String s){
if(n == null){
//root is null, make it a new node
n = new Node(s);
} else if(s.compareTo(n.getData()) < 0){
//string is alphabetically less than root
n.setLeft(insertHelper(n.getLeft(), s));
n.getLeft().setParent(n);
} else{
//string is alphabetically greater than root
n.setRight(insertHelper(n.getRight(), s));
n.getRight().setParent(n);
}
return n;
}
public void delete(String s){
deleteHelper(root, s.toLowerCase());
}
private void deleteHelper(Node n, String s){
if(n == null){
//nothing to delete
return;
}
//found node to delete
else if(s.equals(n.getData())){
System.out.println("DELETED: " + n.getData());
//check for left subtree
//if null, replace node-to-be-deleted with
//right subtree
if(n.getLeft() == null){
replace(n, n.getRight());
}
//check for right subtree
//if null, replace node-to-be-deleted with
//left subtree
else if(n.getRight() == null){
replace(n, n.getLeft());
}
//if it has two subtrees, find minimum value of the
//right tree and swap the node-to-be-deleted's data with
//the minimum node's data
else{
Node min = n.getRight();
while(min.getLeft() != null){
min = min.getLeft();
}
//replace with right and reset pointers
if(min.getParent() != n){
replace(min, min.getRight());
min.setRight(n.getRight());
min.getRight().setParent(min);
}
//replace with left and reset pointers
else{
replace(n, min);
min.setLeft(n.getLeft());
min.getLeft().setParent(min);
}
}
}
//if it hasn't been found, recurse left
else if(s.compareTo(n.getData()) < 0){
deleteHelper(n.getLeft(), s);
}
//then, recurse right
else{
deleteHelper(n.getRight(), s);
}
}
private void replace(Node x, Node y){
//if x is the root, set root to y
if(x.getParent() == null){
root = y;
}
//if x is a left child, set it's parent's left child to y
else if(x == x.getParent().getLeft()){
x.getParent().setLeft(y);
}
//if x is a right child, set it's parent's right child to y
else{
x.getParent().setRight(y);
}
//if y is not null, set y's parent to be x's parent
if(y != null){
y.setParent(x.getParent());
}
}
public void destroy(){
//wipe out the tree
root = null;
size = 0;
}
public boolean find(String s){
return findHelper(root, s.toLowerCase());
}
public boolean findHelper(Node n, String s){
if(n == null){
System.out.println("Sorry, " + s + " is not in here.");
return false;
}
if(s.equals(n.getData())){
System.out.println(s + " is in the tree.");
return true;
} else if(s.compareTo(n.getData()) < 0){
return findHelper(n.getLeft(), s);
} else{
return findHelper(n.getRight(), s);
}
}
}
public class SearchDriver {
/**
* #param args
*/
public static void main(String[] args) {
SearchDriver me = new SearchDriver();
me.doIt();
}
public void doIt(){
BinarySearchTree tree = new BinarySearchTree();
tree.insert("marry");
tree.insert("alpha");
tree.insert("gamma");
tree.insert("delta");
tree.insert("epsilon");
tree.insert("zeta");
tree.insert("eta");
tree.insert("theta");
tree.insert("iota");
tree.insert("kappa");
tree.insert("lambda");
tree.insert("beta");
tree.insert("nu");
tree.insert("xi");
tree.insert("omicron");
tree.insert("pi");
tree.insert("rho");
tree.insert("sigma");
tree.insert("tau");
tree.insert("upsilon");
tree.insert("phi");
tree.insert("chi");
tree.insert("psi");
tree.insert("omega");
tree.printInOrder();
tree.delete("psi");
tree.printInOrder();
tree.delete("marry");
tree.printInOrder();
tree.printPostOrder();
}
}

Let me help you:
Build your program in an IDE
Set a breakpoint at the start of your main method
Start your program in a debugger
Step through the code with the scenario where root is being deleted
If you cannot solve this problem with the advice given above, put a comment in this question as to what specifically you were stuck on. If you don't take the time now to learn these skills, it will haunt you forever and ever in your programming profession.

The problem is with:
if (min.getParent() != n) {
replace(min, min.getRight());
min.setRight(n.getRight());
min.getRight().setParent(min);
}
This is never replacing n with min so root is never being set to its new value.

Related

Homework help: Array being weird [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 4 years ago.
I'm working on a Binary Search Tree assignment, and I was testing what I thought was the finished product when I saw that when I added a number to the tree and then tried to check it's predecessor/successor (by putting it into an array using in order traverse and then checking the index before/after it) it just...didn't work. Any time I try to check the predecessor/successor of a value I just put in the middle of the tree, it wigs out with an ArrayIndexOutOfBoundsException. Important note is that simply printing out using inordertraverse (called printInOrder in the code) works perfectly.
Since printing the inorder traverse works, I can assume my tree isn't the problem. The only other thing is the array, right? Am I missing something obvious?
Here's the code!
public class BST implements BSTInterface
{
//Variables/Fields
private BNode root;
//Constructors
public BST(int data)
{
root = new BNode(data);
}
//Public Methods
public boolean add(int data)
{
if(!contains(data))
{
root = addEntry(root, data);
return true;
}
else
return false;
}
public boolean contains(int data)
{
return containsNode(root, data);
}
public boolean remove(int data)
{
if(contains(data))
{
root = deleteNode(root, data);
return true;
}
else
return false;
}
public int[] toArray()
{
int[] output = new int[root.numNodes()];
inorderTraverse(output, 0, root);
return output;
}
public void printInOrder()
{
printIn(root);
}
public void printPreOrder()
{
printPre(root);
}
public void printPostOrder()
{
printPost(root);
}
//Private methods/classes
private class BNode
{
private int data;
private BNode leftChild;
private BNode rightChild;
public BNode(int data)
{
this.data = data;
leftChild = null;
rightChild = null;
}
public int getData()
{
return data;
}
public void setData(int newData)
{
data = newData;
}
public BNode getLeftChild()
{
return leftChild;
}
public BNode getRightChild()
{
return rightChild;
}
public void setRightChild(BNode node)
{
rightChild = node;
}
public void setLeftChild(BNode node)
{
leftChild = node;
}
public int numNodes()
{
int leftNum = 0;
int rightNum = 0;
if(leftChild != null)
leftNum = leftChild.numNodes();
if(rightChild != null)
rightNum = rightChild.numNodes();
return 1+leftNum+rightNum;
}
}
private BNode addEntry(BNode current, int data)
{
if(current == null)
return new BNode(data);
if(data < current.getData())
current.setLeftChild(addEntry(current.getLeftChild(), data));
else if(data > current.getData())
current.setRightChild(addEntry(current.getRightChild(), data));
return current;
}
private boolean containsNode(BNode current, int entry)
{
if(current == null)
return false;
if(entry == current.getData())
return true;
if(entry < current.getData())
return containsNode(current.getLeftChild(), entry);
else
return containsNode(current.getRightChild(), entry);
}
private BNode deleteNode(BNode current, int data)
{
if(current == null)
return null;
if(data == current.getData())
{
if(current.getLeftChild() == null && current.getRightChild() == null) //No children
return null;
if(current.getRightChild() == null) //Only right child
return current.getLeftChild();
if(current.getLeftChild() == null) //Only left child
return current.getRightChild();
int smallestChild = findSmallest(current.getRightChild());
current.setData(smallestChild);
current.setRightChild(deleteNode(current.getRightChild(), smallestChild));
return current;
}
if(data < current.getData())
{
current.setLeftChild(deleteNode(current.getLeftChild(), data));
return current;
}
else
current.setRightChild(deleteNode(current.getRightChild(), data));
return current;
}
private int findSmallest(BNode root)
{
return root.getLeftChild() == null ? root.getData() : findSmallest(root.getLeftChild());
}
private void inorderTraverse(int[] array, int count, BNode node)
{
if(node != null)
{
inorderTraverse(array, count, node.getLeftChild());
array[count] = node.getData();
count++;
inorderTraverse(array, count, node.getRightChild());
}
}
private void printIn(BNode node)
{
if(node != null)
{
printIn(node.getLeftChild());
System.out.print(node.getData() + " ");
printIn(node.getRightChild());
}
}
private void printPre(BNode node)
{
if(node != null)
{
System.out.print(node.getData() + " ");
printPre(node.getLeftChild());
printPre(node.getRightChild());
}
}
private void printPost(BNode node)
{
if(node != null)
{
printPost(node.getLeftChild());
printPost(node.getRightChild());
System.out.print(node.getData() + " ");
}
}
}
along with the driver program:
import java.util.Scanner;
public class BSTDemoReel
{
public static void main(String[] args)
{
System.out.println("This search tree only handles integers! Thanks in advance!\n\n");
Scanner keyboard = new Scanner(System.in);
//Variables
String input;
String choice = "";
int num;
int index;
boolean found;
//Starting
System.out.println("Please enter the initial sequence of values:\n");
input = keyboard.nextLine();
String[] splitInput = input.split(" ");
int[] intInputArray = new int[splitInput.length];
for(int count = 0; count < splitInput.length; count++)
{
intInputArray[count] = Integer.parseInt(splitInput[count]);
}
BST searchTree = new BST(intInputArray[0]);
for(int count = 1; count < intInputArray.length; count++)
{
searchTree.add(intInputArray[count]);
}
System.out.print("Pre-order: ");
searchTree.printPreOrder();
System.out.println();
System.out.print("In-order: ");
searchTree.printInOrder();
System.out.println();
System.out.print("Post-order: ");
searchTree.printPostOrder();
System.out.println();
//Menu
while(!choice.equals("E"))
{
System.out.print("Command? ");
choice = keyboard.next();
choice = choice.toUpperCase();
switch(choice)
{
case "I": num = keyboard.nextInt();
if(searchTree.contains(num))
System.out.println(num + " already exists. Please try again.");
else
{
searchTree.add(num);
System.out.print("In-order: ");
searchTree.printInOrder();
System.out.println();
}
break;
case "D": num = keyboard.nextInt();
if(!searchTree.contains(num))
System.out.println(num + " does not exist. Please try again.");
else
{
searchTree.remove(num);
System.out.print("In-order: ");
searchTree.printInOrder();
System.out.println();
}
break;
case "P": num = keyboard.nextInt();
if(searchTree.contains(num))
{
int[] array = searchTree.toArray();
index = 0;
found = false;
while(!found)
{
if(num == array[index])
found = true;
else
index++;
}
if(index != 0)
System.out.println(array[index-1]);
else
System.out.println("That was the first one!");
}
else
System.out.println(num + " does not exist! Please try again!");
break;
case "S": num = keyboard.nextInt();
if(searchTree.contains(num))
{
int[] array = searchTree.toArray();
index = 0;
found = false;
while(!found)
{
if(num == array[index])
found = true;
else
index++;
}
if(index != array.length-1)
System.out.println(array[index+1]);
else
System.out.println("That was the last one!");
}
else
System.out.println(num + " does not exist! Please try again!");
break;
case "E": System.out.println("Was a tricky one! Thanks for playing ;P");
break;
case "H": System.out.println("I Insert a value\n" +
"D Delete a value\n" +
"P Find predecessor\n" +
"S Find successor\n" +
"E Exit the program\n" +
"H Display this message");
break;
default: System.out.println("Invalid command. Type H for help.");
break;
}
}
keyboard.close();
}
}
If you add a couple of lines of code to print out the array returned by searchTree.toArray() before you enter the while loop that examines the array to find the value specified with the P or S commands then you'll see the cause of the problem. The array is not filled in correctly. The desired value might not be present in the array, which means that found will never become True and the while loop will continue to increment index until it exceeds the size of the array and triggers the exception that you're seeing.
Since the array is supposed to be populated by inorderTraverse(), this suggests that that function isn't doing its job correctly. The reason why it is misbehaving is that its inner recursive calls to itself do not modify the value of the count variable for the caller. count is a simple int variable, therefore the count++ statement inside the recursive call does not affect the value of count in the calling function.
Your best options are either to change inorderTraverse() so that it returns the index of the array element that should be filled in next, or change count to be an Object that contains an int member whose updated value will be visible to the caller after it has been incremented inside the recursively called function.
Since this is an assignment I'm not going to show a corrected version of the program. The change is small, so given what you've done so far I expect that you won't have much trouble making it work.
BTW, your program is missing implementations of printIn(), printPre() and printPost(). They're not hard to write, but it's an extra hurdle for anyone who might have been interested in helping you tackle the problem. That might be at least part of the reason why no-one else has offered an answer yet. The easier you make it for people to reproduce the problem, the more likely it is that you'll get answers.

Illegal start of expression with <> [duplicate]

This question already has answers here:
What is the point of the diamond operator (<>) in Java?
(7 answers)
Closed 5 years ago.
I keep on getting this whenever I run my code with -Xlint:
Tester.java:11: error: illegal start of type
DoubleThreadedBST<> BST = new DoubleThreadedBST()<>;
^
Tester.java:11: error: illegal start of expression
DoubleThreadedBST<> BST = new DoubleThreadedBST()<>;
^
Tester.java:11: error: illegal start of expression
DoubleThreadedBST<> BST = new DoubleThreadedBST()<>;
the code is meant to make a double threaded binary search treee. I'd like to actually test my code but I keep on getting these errors
my code:
DoubleThreadedBST
Code is selfexplanitory(also has comments)
public class DoubleThreadedBST<T extends Comparable<? super T>>
{
private DTNode<T> root; // the root node of the tree
public static boolean dLeft;
public static boolean dRight;
/*
TODO: You must complete each of the methods in this class to create
your own double threaded BST. You may add any additional methods
or data fields which you might need to accomplish your task. You
must NOT change the signatures of any methods given to you with this
class.
*/
public DoubleThreadedBST()
{
root = null;
}
public DoubleThreadedBST(DoubleThreadedBST<T> other)
{
root = other.getRoot();
}
public DoubleThreadedBST<T> clone()
{
DoubleThreadedBST<T> other = new DoubleThreadedBST<T>();
other.setRoot(this.root);
return other;
}
public DTNode<T> getRoot()
{
return root;
}
public void setRoot(DTNode<T> r){
root = r;
}
public boolean insert(T element){
DTNode<T> newNode = new DTNode<T>(element);
if(root != null){
if(contains(element) == false){
if(root.hasLeftT() != true){
root.setLeft(newNode);
root.setHasLeftT(true);
root.setLeftBit(1);
newNode.setRight(root);
newNode.setHasRightT(true);
newNode.setRightBit(0);
return true;
}else if (root.hasRightT() != true){
root.setRight(newNode);
root.setHasRightT(true);
root.setRightBit(1);
newNode.setLeft(root);
newNode.setHasLeftT(true);
newNode.setLeftBit(0);
return true;
}else{
DTNode<T> trav = root.getLeft();
while(true){
if(trav.getData().compareTo(newNode.getData()) == 1){
if(trav.getLeftBit() == 0){
newNode.setLeft (trav.getLeft());
trav.setLeft(newNode);
newNode.setLeftBit (trav.getLeftBit());
trav.setLeftBit(1);
newNode.setRight(trav);
break;
}else{
trav = trav.getLeft();
}
}else{
if(trav.getRightBit() == 0){
newNode.setRight(trav.getRight());
trav.setRight(newNode);
newNode.setRightBit(trav.getRightBit());
trav.setRightBit(1);
newNode.setLeft(trav);
break;
}else{
trav = trav.getRight();
}
}
}
}
}else{
return false;
}
}else{
root = newNode;
root.setLeft(null);
root.setRight(null);
root.setHasLeftT(false);
root.setHasRightT(false);
return true;
}
/*
The element passed in as a parameter should be
inserted into this tree. Duplicates are not allowed.
Left and right threads in the corresponding branch
must be updated accordingly, as necessary.
If the insert was successfull, the method should
return true. If the operation was unsuccessfull,
the method should return false.
NB: Do not throw an exception.
*/
return true;
}
/*
public boolean delete(T element){
if(contains(element){
DTNode<T> trav = root;
while (trav.getLeft()!= null){
trav = trav.getLeft();
}
while(trav != null){
if(trav.getRight().getData() == element){
DTNode<T> temp = trav.getRight();
trav.setRight(keeper.getRight());
while (temp 1= null){
}
}
if(trav.hasRightT()){
trav = trav.getRight();
}else{
trav = trav.getLeft();
}
}
}
*/
/*
The element passed in as a parameter should be
deleted from this tree. If the delete was successfull,
the method should return true. If the operation was
unsuccessfull, the method should return false. Eg, if
the requested element is not found, return false.
You have to implement the mirror case of delete by merging
as discussed in the textbook. That is, for a deleted node,
its right child should replace it in the tree and not its
left child as in the textbook examples. Relevant left and
right threads must be updated accordingly.
NB: Do not throw an exception.
return false;
}
*/
public boolean contains(T element){
if(root != null){
DTNode<T> trav = root;
while (trav.getLeft()!= null){
trav = trav.getLeft();
}
while(trav != null){
if(trav.getData() == element){
return true;
}
if(trav.hasRightT()){
trav = trav.getRight();
}else{
trav = trav.getLeft();
}
}
}
return false;
}
public String inorderAscending(){
String tree = "";
if(root != null){
DTNode<T> trav = root;
while (trav.getLeft()!= null){
trav = trav.getLeft();
}
while(trav != null){
tree += trav.getData();
if(trav.getRight() != null){
tree += ",";
}
if(trav.hasRightT()){
trav = trav.getRight();
}else{
trav = trav.getLeft();
}
}
}
/*
This method must return a string representation
of the elements in the tree inorder, left to right.
This function must not be recursive. Instead, right
threads must be utilised to perform a depth-first
inorder traversal.
If the tree looks like:
B
/ \
A D
/ \
C E
Then the following string must be returned:
A,B,C,D,E
Note that there are no spaces in the string, and
the elements are comma-separated.
*/
return tree;
}
public String inorderDescending(){
String tree = "";
if(root != null){
DTNode<T> trav = root;
while (trav.getRight()!= null){
trav = trav.getRight();
}
while(trav != null){
tree += trav.getData();
if(trav.getLeft() != null){
tree += ",";
}
if(trav.hasLeftT()){
trav = trav.getLeft();
}else{
trav = trav.getRight();
}
}
}
/*
This method must return a string representation
of the elements in the tree inorder, right to left.
This function must not be recursive. Instead, left
threads must be utilised to perform a depth-first
inorder traversal.
If the tree looks like:
B
/ \
A D
/ \
C E
Then the following string must be returned:
E,D,C,B,A
Note that there are no spaces in the string, and the elements are comma-separated.
*/
return tree;
}
public int countRightThreads(){
int count = 0;
if(root != null){
DTNode<T> trav = root;
while (trav.getRight() != null){
trav = trav.getRight();
count ++;
}
while(trav != null){
if(trav.hasLeftT()){
trav = trav.getLeft();
}else{
count++;
trav = trav.getRight();
}
}
}
/*
This method should return the total number of right threads
in the tree.
*/
return count;
}
public int countLeftThreads(){
int count = 0;
if(root != null){
DTNode<T> trav = root;
while (trav.getLeft()!= null){
trav = trav.getLeft();
count++;
}
while(trav != null){
if(trav.hasLeftT()){
trav = trav.getLeft();
count ++;
}else{
trav = trav.getRight();
}
}
}
/*
This method should return the total number of left threads
in the tree.
*/
return count;
}
public int getNumberOfNodes()
{
int count = 0;
if(root != null){
DTNode<T> trav = root;
while (trav.getLeft()!= null){
trav = trav.getLeft();
count++;
}
while(trav != null){
if(trav.hasLeftT()){
trav = trav.getLeft();
count ++;
}else{
trav = trav.getRight();
count++;
}
}
}
/*
This method should count and return the number of nodes
currently in the tree.
*/
return count;
}
public int getHeight()
{
/*
This method should return the height of the tree. The height
of an empty tree is 0; the height of a tree with nothing but
the root is 1.
*/
return 0;
}
}
Tester
Just for testing
public class Tester
{
public static void main(String[] args) throws Exception
{
/*
TODO: Write your code to test your implementation here.
This file will be overwritten for marking purposes
*/
DoubleThreadedBST<> BST = new DoubleThreadedBST()<>;
BST.insert(1);
BST.insert(2);
BST.insert(3);
BST.insert(5);
BST.insert(4);
System.out.println(BST.inorderAscending());
System.out.println(BST.inorderDescending());
}
}
DTNode
Has a left and a right while my ...Bits show whether they left and right are pointing to an in order parent or a child node.
public class DTNode<T extends Comparable<? super T>>
{
/*
TODO: You must implement a node class which would be appropriate to use with your trees.
Methods and variables can be added.
Names of the given variables must not be altered.
*/
//setters
public DTNode(){
}
public DTNode(T elem){
data = elem;
}
public void setLeft(DTNode<T> n){
left = n;
}
public void setRight(DTNode<T> n){
right = n;
}
public void setData(T elem){
data = elem;
}
public void setHasLeftT(boolean t){
hasLeftThread = t;
}
public void setHasRightT(boolean t){
hasRightThread = t;
}
public void setLeftBit(int b){
leftBit = b;
}
public void setRightBit(int b){
rightBit= b;
}
//getters
public DTNode<T> getLeft(){
return left;
}
public DTNode<T> getRight(){
return right;
}
public T getData(){
return data;
}
public boolean hasLeftT(){
return hasLeftThread;
}
public boolean hasRightT(){
return hasRightThread;
}
public int getLeftBit(){
return leftBit;
}
public int getRightBit(){
return rightBit;
}
protected T data;
protected DTNode<T> left, right; // left child and right child
protected boolean hasLeftThread, hasRightThread; // flags that indicate whether the left and the right pointers are threads
protected int leftBit, rightBit;
}
Reference declaration doesnt accept diamond operator, which means you have to send a generic argument. Repleace this:
DoubleThreadedBST<> BST = new DoubleThreadedBST()<>;
with:
DoubleThreadedBST<Integer> BST = new DoubleThreadedBST<>();

How to store the number of times a recursion method calls itself by use of binary tree

I couldn't figure out how to store the number of times a recursive method calls itself. If any one could point me in the right direction I would greatly appreciate it! Below is my code in it i have a comment on where I think I am going wrong.
package module8_auriemma_assignment;
import java.util.*;
public class fibonacciTree{
Node root;
public void addNode(int key, int num) {
Node newNode = new Node(key, num);
if (root == null) {
root = newNode;
}
else {
Node focusNode = root;
Node parent;
while (true) {
parent = focusNode;
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
if (focusNode == null) {
parent.leftChild = newNode;
return;
}
}
else
{
focusNode = focusNode.rightChild;
if (focusNode == null) {
// then place the new node on the right of it
parent.rightChild = newNode;
return; // All Done
}
}
}
}
}
public static void main(String[] args) {
fibonacciTree theTree = new fibonacciTree();
Scanner input = new Scanner (System.in);
System.out.println("Please enter an index");
System.out.println("I will compute your index's Fibonacci numbers.");
System.out.println("I will compute numbers that do not exceed a billion");
int number;
int key;
key = 0;
for(number = input.nextInt(); number < 1000000; number++){
System.out.println(fibonacci(number));
theTree.addNode(key, number);
/*
I am not sure if I should be adding a new node everytime the
loop happens in the main class OR if I should be having it store
a node inside of the fibonacci method itself
*/
number++;
key++;
}
}
public static long fibonacci(int i)
{
if (i == 0) return 0;
if (i <= 2) return 1;
long fibTerm = fibonacci(i - 1) + fibonacci(i - 2);
if(fibTerm > 1000000000){
System.out.println("Number too large");
System.exit(0);
}
else{
return fibTerm;
}
return fibTerm;
}
}
.
package module8_auriemma_assignment;
class Node {
int key;
int num;
Node leftChild;
Node rightChild;
Node(int key, int num) {
this.key = key;
this.num = num;
}
#Override
public String toString() {
return num + " has the key " + key;
}
}
fibonacci(int i) keeps calling itself until it is reduced to a series of 1+1+1+1+1+1+1+1+1+1+1+...
The solution is also the number of times the method is called. If you want to know how many times it was called, look at the return value.

Recursively Traverse a Binary Search Tree And Print Out Data In Columns

I have constructed a binary search tree using a text file that is read in by the main function. The resulting tree contains the words of the text file, with a count so that the same word is not inserted twice. The problem is not with constructing the tree, but getting the information to display properly. The data is required to be printed out in columns of 4, as to keep it readable.
Example:
|BTNode1|BTNode2|BTNode3|BTNode4|
|BTNode5|BTNode6|BTNode7|BTNode8|
The BTNode class has a toString() method that prints out the data of the individual nodes. But, whenever I call this code below with the root node, and a count of 0 I get the node information properly, but in weird numbers of nodes per column. Any ideas how to get this to work? I can post additional code if necessary.
EDIT: Added entire class to reflect changes, and added sample current output. Might be a problem with constructing the tree.
EDIT2: Changed printcount = 1, fixes the display problems. Code now works properly.
package speech;
public class BSTree {
private BTNode root;
private final String DISPLAY_FORMAT_CAPS =
"*****************************************************************";
private StringBuilder buffer = new StringBuilder();
private int printcount = 1;
public BSTree (){
root = null;
}
public BTNode insert(String indata, boolean lowercase){
if(lowercase){
if(root != null){
return insertRecursive(root,indata.toLowerCase());
}
else{
root = new BTNode(indata.toLowerCase());
return root;
}
}
else{
if(root != null){
return insertRecursive(root,indata);
}
else{
root = new BTNode(indata);
return root;
}
}
}
private BTNode insertRecursive(BTNode node, String value) {
if (value.compareTo(node.data) < 0){
if (node.left != null) {
return insertRecursive(node.left, value);
} else {
//System.out.println(" Inserted " + value + " to left of Node " + node.data);
node.left = new BTNode(value);
return node.left;
}
} else if (value.compareTo(node.data) > 0) {
if (node.right != null) {
return insertRecursive(node.right, value);
} else {
//System.out.println(" Inserted " + value + " to right of Node " + node.data);
node.right = new BTNode(value);
return node.left;
}
} else if (value.compareTo(node.data) == 0){
node.incrementCount();
//System.out.println("Incremented count of " + value + " to: " + node.wordcount);
return node;
}
return null;
}
private int wordcountRecursive(BTNode node){
if(node == null){
return 0;
}
else{
return wordcountRecursive(node.left) + node.wordcount + wordcountRecursive(node.right);
}
}
public int wordcount(){
return wordcountRecursive(root);
}
public void display(){
System.out.println(DISPLAY_FORMAT_CAPS);
displayRecursive(root);
System.out.println(buffer.toString());
System.out.println(DISPLAY_FORMAT_CAPS);
System.out.println("Word Count:" + wordcount());
}
private void displayRecursive (BTNode node){
//System.out.println(count);
if(node != null){
displayRecursive(node.left);
addNodeDisplay(node);
displayRecursive(node.right);
}
}
private void addNodeDisplay(BTNode node){
if(printcount % 4 != 0){
buffer.append("|").append(node);
}
else{
buffer.append("|").append(node).append("|\n");
}
printcount++;
}
}
I've added some sample data and this looks like it works:
private void displayRecursive(Node node) {
displayRecursive(node, 0);
System.out.println("");
}
private int displayRecursive(Node node, int count) {
if (node != null) {
// Do left first.
count = displayRecursive(node.getLeft(), count);
// New line?
if (count > 0 && count % 4 == 0) {
// End of line.
System.out.println("|");
}
// Then me.
System.out.print("|" + node);
count += 1;
// Then right.
count = displayRecursive(node.getRight(), count);
}
return count;
}
private void test() {
Node root = new Node("Root");
Node left = new Node("Left");
Node right = new Node("Right");
root.setLeft(left);
root.setRight(right);
Node leftLeft = new Node("Left.Left");
leftLeft.setLeft(new Node("LeftLeftLeft"));
leftLeft.setRight(new Node("LeftLeftRight"));
left.setLeft(leftLeft);
left.setRight(new Node("Left.Right"));
right.setLeft(new Node("Right.Left"));
right.setRight(new Node("Right.Right"));
displayRecursive(root);
}
public static void main(String[] args) throws InterruptedException {
try {
Test test = new Test();
test.test();
} catch (Exception e) {
e.printStackTrace();
}
}
static class Node {
final String data;
private Node left = null;
private Node right = null;
Node(String data) {
this.data = data;
}
#Override
public String toString() {
return data;
}
/**
* #return the left
*/
public Node getLeft() {
return left;
}
/**
* #param left the left to set
*/
public void setLeft(Node left) {
this.left = left;
}
/**
* #return the right
*/
public Node getRight() {
return right;
}
/**
* #param right the right to set
*/
public void setRight(Node right) {
this.right = right;
}
}
it prints:
|LeftLeftLeft|Left.Left|LeftLeftRight|Left|
|Left.Right|Root|Right.Left|Right|
|Right.Right

Problem with balancing a rotation in an AVL tree JAVA

Im writing a basic AVL tree that holds Objects, im having a Stackoverflow error (lol) in my code to recurse through the tree to get the height of the current node. I dont think my height code is actually the problem so much that my rotation causes my height code to have the problem.
So what I do is I recurse through the children of the node until I reach a null node which returns 0, the next/preceding call (depending on how you look at it) returns the maximum of the return the call on that node + 1 vs whatever the call on the other child ends up being. It should be pretty clear how it works when you see it.
the rotation creates a temporary node from the appropriate child and alters the node and sets it to the child of the temporary node and sets the parent values to the proper nodes. (Each node has a reference not only to a left and right node but the parent node)
The insertion method works fine as far as I can tell, I do have a problem with an infinite loop in my delete method but thats another question for another time.
Hopefully I have given enough info, let me know if there is anything I can clarify this is my first post here. but any help is appreciated, this one even has my instructor stumped.
Thanks for even taking the time to read this wall of text.
import java.lang.Math;
/**
This is an AVL binary search tree class it uses a AVLNode to create an AVL Binary search tree.
*/
public class AVLTree {
AVLNode root;
Index empty;
public AVLTree(){
root = null;
}
public void insert(Object o, String ssNumber){
if (root == null){
root = new AVLNode(o);
System.out.print("adding root");
}
else{
AVLNode current = root;
AVLNode node = new AVLNode(o);
while (current != null){
if (((Comparable)current.getData()).compareTo(ssNumber) < 0){
if (current.getRight() != null){
current = current.getRight();
}
else{
// System.out.println(((Index)(current.getData())).getSocial() + " CURRENT DATA");
current.setRight(node);
current.getRight().setParent(current);
// System.out.println("adding " + ((Index)o).getSocial() + "to the right of" + ((Index)(current.getData())).getSocial());
balanceTree(current);
// if (current.getParent() != null)
// System.out.println("the right child of " + (((Index)(current.getParent().getData())).getSocial()) + " is now " + (((Index)((current.getRight()).getData())).getSocial()) );
current=null;
}
}
else if (((Comparable)current.getData()).compareTo(ssNumber) > 0) {
if (current.getLeft()!= null){
current = current.getLeft();
}
else{
// System.out.println(((Index)(current.getData())).getSocial() + " CURRENT DATA");
current.setLeft(node);
current.getLeft().setParent(current);
// System.out.println("adding " + ((Index)o).getSocial() + "to the left of" + ((Index)(current.getData())).getSocial());
balanceTree(current);
// if (current.getParent() != null)
// System.out.println("the left child of " + (((Index)(current.getParent().getData())).getSocial()) + " is now " + (((Index)((current.getLeft()).getData())).getSocial()) );
current=null;
}
}
}
}
}
public boolean delete(String ssNumber){
AVLNode current = root;
AVLNode parent = null;
while (current.getData() != null){
if (((Comparable)current.getData()).compareTo(ssNumber) > 0){
if(current.getLeft() != null){
parent = current;
current = current.getLeft();
}
else{
//System.out.print(((Index)(current.getData())).getSocial() + "not found");
return false;
}
}
else if (((Comparable)current.getData()).compareTo(ssNumber) < 0){
if (current.getRight()!=null){
parent = current;
current = current.getRight();
}
else{
//System.out.print(((Index)(current.getData())).getSocial() + "not found");
return false;
}
}
else{
if (current.getLeft() != null && current.getRight() != null){
AVLNode leftHighest = null;
AVLNode temp = current.getLeft();
while (temp.getRight() != null){
temp = temp.getRight();
}
leftHighest.setData(temp.getData());
temp.setData(current.getData());
current.setData(leftHighest.getData());
return delete(ssNumber);
}
if (current.getLeft() == null && current.getRight() != null){
if (parent == null){
root = current.getRight();
}
if (current == parent.getLeft()){
parent.setLeft(current.getRight());
}
else{
parent.setRight(current.getRight());
}
}
else if (current.getRight() == null && current.getLeft() != null){
if (parent == null){
root = current.getLeft();
}
if (current == parent.getLeft()){
parent.setLeft(current.getLeft());
}
else{
parent.setRight(current.getLeft());
}
}
else{
current.setData(null);
return true;
}
}
}
//System.out.print(((Index)(current.getData())).getSocial() + "not found");
return false;
}
public int find(String ssNumber){
AVLNode current = root;
while (current.getData() != null){
if (((Comparable)current.getData()).compareTo(ssNumber) > 0){
if(current.getLeft() != null){
current = current.getLeft();
}
else{
//System.out.print(((Index)(current.getData())).getSocial() + "not found");
return -1;
}
}
else if (((Comparable)current.getData()).compareTo(ssNumber) < 0){
if (current.getRight()!=null){
current = current.getRight();
}
else{
//System.out.print(((Index)(current.getData())).getSocial() + "not found");
return -1;
}
}
else{
return ((Index)(current.getData())).getArrayIndex();
}
}
return -1;
}
public void clear(){
root = null;
}
//gets the height of the node's subtrees. Uses recursion to find the max height returns the highest value of each traversal adding 1 for each step.
private int getHeight(AVLNode node){
if (node == null){
return 0;
}
else
{
//int x = getHeight( node.getLeft() );
//int y = getHeight( node.getRight() );
//return Math.max( x, y ) + 1;
return Math.max(getHeight(node.getLeft()), getHeight(node.getRight())) + 1;
}
}
//uses the value of getBalance to decide which type of rotation to undergo, and rotates the node by creating a temporary node from the proper child based on the type value.
//the type value will be passed the balance.
private AVLNode rotateNodes(AVLNode node, int type){
AVLNode temp;
//System.out.println("step C");
if (type == -2){
temp = node.getRight();
temp.setParent(node.getParent());
if (node.getParent() != null){
if (node == node.getParent().getLeft()){
temp.getParent().setLeft(temp);
}
else{
temp.getParent().setRight(temp);
}
}
node.setRight(temp.getLeft());
if (node.getRight() != null){
node.getRight().setParent(node);
}
temp.setLeft(node);
return temp;
}
else if (type == 2){
temp = node.getLeft();
temp.setParent(node.getParent());
if (node.getParent() != null){
if (node == node.getParent().getLeft()){
temp.getParent().setLeft(temp);
}
else{
temp.getParent().setRight(temp);
}
}
node.setLeft(temp.getRight());
if (node.getLeft() != null){
node.getLeft().setParent(node);
}
temp.setRight(node);
node.setParent(temp);
return temp;
}
else
return node;
}
// Runs the methods necessary to balance a tree on each node until it reaches the root.
private void balanceTree(AVLNode node){
AVLNode temp;
while (node != null){
int balance = getHeight(node.getLeft()) - getHeight(node.getRight());
if (balance == 2 || balance == -2){
//System.out.println("step a");
temp = rotateNodes(node, balance);
//System.out.println("rotated");
node.setData(temp.getData());
node.setLeft(temp.getLeft());
node.setRight(temp.getRight());
node.setParent(temp.getParent());
}
else {
//System.out.println("moving on");
node = node.getParent();
}
}
}
//check balance
}
/**
This is an AVL node in a AVL binary tree it contains data and references to its two possible children and it's parent.
*/
public class AVLNode {
private Object data;
private AVLNode left;
private AVLNode right;
private AVLNode parent;
public AVLNode(Object o){
data = o;
left = null;
right = null;
parent = null;
}
public AVLNode(){
data = null;
left = null;
right = null;
parent = null;
}
public Object getData(){
return data;
}
public AVLNode getLeft(){
return left;
}
public AVLNode getRight(){
return right;
}
public void setData(Object index){
data = index;
}
public void setLeft(AVLNode node){
left = node;
}
public void setRight(AVLNode node){
right = node;
}
public void setParent(AVLNode node){
parent = node;
}
public AVLNode getParent(){
return parent;
}
}
/**
The is a person class it holds 6 data fields about a person
*/
public class Person {
private String lastName;
private String firstName;
private String socialSec;
private String phoneNum;
private char gender;
private String date;
public Person(String lastName, String firstName, String socialSec, String phoneNum, char gender, String date) {
this.lastName = lastName;
this.firstName = firstName;
this.socialSec = socialSec;
this.phoneNum = phoneNum;
this.gender = gender;
this.date = date;
}
public String getLast(){
return lastName;
}
public String getFirst(){
return firstName;
}
public String getSocial(){
return socialSec;
}
public void setSocial(String string){
this.socialSec = string;
}
public String getPhone(){
return phoneNum;
}
public char getGender(){
return gender;
}
public String getDate(){
return date;
}
public String toString(){
return ("Lastname: " + lastName + "\nFirstname: " + firstName + "\nSocial Security " + socialSec +
"\nPhone Number: " + phoneNum + "\ngender " + gender);
}
}
/**
This is an index object it will contain the data type used as reference the binary tree, the social, and the references location in the array
*/
public class Index implements Comparable {
String social;
int arrayIndex;
public Index(String social, int arrayIndex) {
this.social = social;
this.arrayIndex = arrayIndex;
}
public String getSocial(){
return social;
}
public void setSocial(String social){
this.social = social;
}
public int getArrayIndex(){
return arrayIndex;
}
public void setArrayIndex(int arrayIndex){
this.arrayIndex = arrayIndex;
}
public int compareTo(Object o){
return social.compareTo((String)o);
}
}
Here is the data read in from datafile (this is fake info)
Hattell Zara 568472178 9562266952 F 8/23/1985
Poff Naomi 070028388 1868991633 F 10/25/1967
Jackson Finley 766879776 6317272316 M 8/28/1984
Lark Kasey 278473635 4953108522 F 9/19/1967
Grifith Josh 223948515 5916186412 M 11/21/1964
Grimsby Mitchel 057848901 4921537476 M 10/28/1969
Heesicker Samara 578308596 0089823308 F 7/27/1964
Amos Kasey 148842321 7949241129 F 2/10/1985
Johnson Angeline 003513447 8828061677 F 4/21/1977
Aldridge John 418953690 5006720120 M 6/23/1968
Mckibbon Vasilios 523212165 0040010068 M 7/30/1972
Woodhouse Jacob 522626205 6985940430 M 7/31/1966
Newell Shante 022753752 8483983762 F 2/24/1978
Ramer Tyler 025694346 6123635287 M 9/14/1980
Leatherman Tige 297071697 1106435680 M 8/11/1981
Johnston Halle 263543220 3417907710 F 11/17/1960
Aber Myah 669617355 3276358736 F 12/10/1961
Frizzle Archie 150388947 1472418810 M 8/5/1960
Mcdivit Ashley 294735567 2017661755 M 11/3/1978
Jackson Sophie 698928462 0185800213 F 3/18/1960
Bechtel William 700321659 1376473348 M 11/30/1974
Larimer Alessi 745219302 2445633750 F 12/12/1964
Bodler Amelie 424759320 2676866912 F 11/25/1961
Niswander Ebony 218384979 7468337166 F 12/3/1970
Overlees Minnesha 594664590 9411189605 F 8/5/1981
Jones Haley 692179128 9046757546 F 3/24/1968
Weiner Lee 111223333 2223334444 M 2/31/1978
/*
main class to create a Binary search tree
*/
import java.io.*;
import java.util.Scanner;
import java.util.regex.*;
import java.util.List;
import java.util.ArrayList;
public class AVLdatabase {
public static void main(String[] args) {
AVLTree anAVLTree = new AVLTree();
File file = new File("datafile.txt");
List<Person> dataArray = new ArrayList<Person>();
try {
Scanner scanner = new Scanner(file);
//read lines and place the data into person objects
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
Scanner lineScanner = new Scanner(line).useDelimiter("\t");
while (lineScanner.hasNext()) {
Person record = new Person(lineScanner.next(),lineScanner.next(),lineScanner.next(),lineScanner.next(),(lineScanner.next()).charAt(0),lineScanner.next());
System.out.print(record.getLast() + " ");
System.out.print(record.getFirst() + " ");
System.out.print(record.getSocial() + " ");
System.out.println();
Index index = new Index(record.getSocial(), dataArray.size());
dataArray.add(record);
anAVLTree.insert(index, record.getSocial());
System.out.println("The array index is " + (dataArray.size()-1));
}
}
}
catch (IOException e) {
System.out.print("No File");
}
}
}
Your height code looks fine. I would assume that your rotation code is causing one of your leaves to link back to an inner node.
E.g.:
A
/ \
B C
May be becoming:
B
/ \
C A
/ \
B C
with A still having a reference to B, which has a reference to A which has a reference to B, which has a reference to A, etc. The A -> B would, of course, be referencing the root B, but I can't picture that here.
You are the best person at debugging your own code, but I can provide some general suggestions:
Not sure if you're aware of this, but in the following code:
temp = node.getRight();
temp.setParent(node.getParent());
Correct me if I'm wrong, but temp is copied by reference, not by value. After these operations, node.getRight().getParent() will equal temp.getParent(). That's probably not the issue, but you should be aware of it.
Watch out for side effects. Whatever you did in the previous line affects the following lines.
Ditch the AVLNode parent; , as maintaining it introduces cruft. Bear in mind that you will probably need to make a recursive subroutine for delete() to keep track of the parent. Alternatively, make your accessor methods for AVLNode automatically maintain parent links.

Categories