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

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

Related

how to create binary search tree 2d model from these codes?

hi im new to codings and i have to print my binary search tree in a 2d model but this codes only print the orders of number in order(left-root-right) such as when i insert 10, 9, 11, 8, it will print inorder (left root right) = 8,9,10,11. what method or codes should i add to create a 2d tree here. sorry idk how to properly put the codes here just look at it like it is only a one code only.
class binarySearchTree {
class Node {
int key;
Node left, right;
int data;
public Node(int data){
key = data;
left = right = null;
}
}
// BST root node
Node root;
// Constructor for BST =>initial empty tree
binarySearchTree(){
root = null;
}
//delete a node from BST
void deleteKey(int key) {
root = delete_Recursive(root, key);
}
//recursive delete function
Node delete_Recursive(Node root, int key) {
//tree is empty
if (root == null) return root;
//traverse the tree
if (key < root.key) //traverse left subtree
root.left = delete_Recursive(root.left, key);
else if (key > root.key) //traverse right subtree
root.right = delete_Recursive(root.right, key);
else {
// node contains only one child
if (root.left == null)
return root.right;
else if (root.right == null)
return root.left;
// node has two children;
//get inorder successor (min value in the right subtree)
root.key = minValue(root.right);
// Delete the inorder successor
root.right = delete_Recursive(root.right, root.key);
}
return root;
}
int minValue(Node root) {
//initially minval = root
int minval = root.key;
//find minval
while (root.left != null) {
minval = root.left.key;
root = root.left;
}
return minval;
}
// insert a node in BST
void insert(int key) {
root = insert_Recursive(root, key);
}
//recursive insert function
Node insert_Recursive(Node root, int key) {
//tree is empty
if (root == null) {
root = new Node(key);
return root;
}
//traverse the tree
if (key < root.key) //insert in the left subtree
root.left = insert_Recursive(root.left, key);
else if (key > root.key) //insert in the right subtree
root.right = insert_Recursive(root.right, key);
// return pointer
return root;
}
void inorder() {
inorder_Recursive(root);
}
// recursively traverse the BST
void inorder_Recursive(Node root) {
if (root != null) {
inorder_Recursive(root.left);
System.out.print(root.key + " x ");
inorder_Recursive(root.right);
}
}
//PostOrder Traversal - Left:Right:rootNode (LRn)
void postOrder(Node node) {
if (node == null)
return;
// first traverse left subtree recursively
postOrder(node.left);
// then traverse right subtree recursively
postOrder(node.right);
// now process root node
System.out.print(node.key + " ");
}
// InOrder Traversal - Left:rootNode:Right (LnR)
void inOrder(Node node) {
if (node == null)
return;
//first traverse left subtree recursively
inOrder(node.left);
//then go for root node
System.out.print(node.key + " ");
//next traverse right subtree recursively
inOrder(node.right);
}
//PreOrder Traversal - rootNode:Left:Right (nLR)
void preOrder(Node node) {
if (node == null)
return;
//first print root node first
System.out.print(node.key + " ");
// then traverse left subtree recursively
preOrder(node.left);
// next traverse right subtree recursively
preOrder(node.right);
}
// Wrappers for recursive functions
void postOrder_traversal() {
postOrder(root); }
void inOrder_traversal() {
inOrder(root); }
void preOrder_traversal() {
preOrder(root); }
}
here i found this codes in stackoverflow, i want te output like this, i can use this but i dont know how can i make this as user input for the data and make it insert the integer into a tree not this manually inserted of the integer. thankyou very much to whoever put effort to understand my question and my situation as newbie.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BTreePrinterTest {
private static Node<Integer> test2() {
Node<Integer> root = new Node<Integer>(2);
Node<Integer> n11 = new Node<Integer>(3);
Node<Integer> n12 = new Node<Integer>(5);
Node<Integer> n21 = new Node<Integer>(2);
Node<Integer> n22 = new Node<Integer>(6);
Node<Integer> n23 = new Node<Integer>(9);
Node<Integer> n31 = new Node<Integer>(5);
root.left = n11;
root.right = n12;
n11.left = n21;
n11.right = n22;
n12.left = n23;
n12.right = n31;
return root;
}
public static void main(String[] args) {
BTreePrinter.printNode(test2());
}
}
class Node<T extends Comparable<?>> {
Node<T> left, right;
T data;
public Node(T data) {
this.data = data;
}
}
class BTreePrinter {
public static <T extends Comparable<?>> void printNode(Node<T> root) {
int maxLevel = BTreePrinter.maxLevel(root);
printNodeInternal(Collections.singletonList(root), 1, maxLevel);
}
private static <T extends Comparable<?>> void printNodeInternal(List<Node<T>> nodes, int level, int maxLevel) {
if (nodes.isEmpty() || BTreePrinter.isAllElementsNull(nodes))
return;
int floor = maxLevel - level;
int endgeLines = (int) Math.pow(2, (Math.max(floor - 1, 0)));
int firstSpaces = (int) Math.pow(2, (floor)) - 1;
int betweenSpaces = (int) Math.pow(2, (floor + 1)) - 1;
BTreePrinter.printWhitespaces(firstSpaces);
List<Node<T>> newNodes = new ArrayList<Node<T>>();
for (Node<T> node : nodes) {
if (node != null) {
System.out.print(node.data);
newNodes.add(node.left);
newNodes.add(node.right);
} else {
newNodes.add(null);
newNodes.add(null);
System.out.print(" ");
}
BTreePrinter.printWhitespaces(betweenSpaces);
}
System.out.println("");
for (int i = 1; i <= endgeLines; i++) {
for (int j = 0; j < nodes.size(); j++) {
BTreePrinter.printWhitespaces(firstSpaces - i);
if (nodes.get(j) == null) {
BTreePrinter.printWhitespaces(endgeLines + endgeLines + i + 1);
continue;
}
if (nodes.get(j).left != null)
System.out.print("/");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(i + i - 1);
if (nodes.get(j).right != null)
System.out.print("\\");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(endgeLines + endgeLines - i);
}
System.out.println("");
}
printNodeInternal(newNodes, level + 1, maxLevel);
}
private static void printWhitespaces(int count) {
for (int i = 0; i < count; i++)
System.out.print(" ");
}
private static <T extends Comparable<?>> int maxLevel(Node<T> node) {
if (node == null)
return 0;
return Math.max(BTreePrinter.maxLevel(node.left), BTreePrinter.maxLevel(node.right)) + 1;
}
private static <T> boolean isAllElementsNull(List<T> list) {
for (Object object : list) {
if (object != null)
return false;
}
return true;
}
}
btw im learning this by my own, i tried merging the two codes but it gives me error i cant fix it.
I should have not made the whole exercise for you, so please try to understand the code. Tell me if something is not clear for you.
public static void main(String[] args) throws IOException {
System.out.println("Write your input");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String lines = br.readLine();
binarySearchTree b = new binarySearchTree();
b.input(lines);
b.print();
}
These functions go to binarySearchTree.
protected void printRecursive(Node node, int depth) {
System.out.println("");
for(int i = 0; i<depth; i++) {
System.out.print(" ");
}
System.out.print(node.key);
if(node.left != null) {
printRecursive(node.left, depth + 1);
}
if(node.right != null) {
printRecursive(node.right, depth + 1);
}
}
public void input(String s) throws IOException {
String[] strs = s.trim().split("\\s+");
for (int i = 0; i < strs.length; i++) {
insert(Integer.parseInt(strs[i]));
}
}
Also i used this answer in my code.

Output( ) from a Set class with Singly Linked List Hash Table

I have code that I have been working on going on 10 hours now, and for the life of me, I am unable to get the output( ) of my Set.java to work. Unfortunately I am not allowed to just import the Iterator or HashTable classes from java library. Any ideas or advice would really help.
public class SLL {
public class Node {
private int data;
private Node next;
public Node() {
data = 0;
next = null;
}
public Node(int newData, Node linkValue) {
data = newData;
next = linkValue;
}
public int getData() {
return data;
}
public Node getLink() {
return next;
}
} // End of Node inner class
private Node head;
public SLL() {
head = null;
}
public void addToStart(int itemData) {
head = new Node(itemData, head);
}
public boolean contains(int item) {
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a reference
* to that node. If target is not in the list, null is returned.
*/
public Node find(int target) {
Node position = head;
int itemAtPosition;
while (position != null) {
itemAtPosition = position.data;
if (itemAtPosition == target) {
return position;
}
position = position.next;
}
return null; // target was not found
}
public void outputList() {
Node position = head;
while (position != null) {
System.out.print(position.data + " ");
position = position.next;
}
System.out.println();
}
}
This is the class that I have been working on:
public class Set {
private SLL[] hashArray; // DO NOT MODIFY THIS LINE
private int size = 10; // DO NOT MODIFY THIS LINE
// DO NOT MODIFY THIS METHOD
public Set() {
hashArray = new SLL[size];
}
// DO NOT MODIFY THIS METHOD
private int computeHash(int s) {
return s % size;
}
// COMPLETE BELOW
public void add(int x)
{
int hash = computeHash(x); // Get hash value
SLL list = hashArray[hash];
if(hashArray[hash] == null)
hashArray[hash] = new SLL();
else if(!list.contains(x));
{
// Only add the target if it's not already
// on the list.
hashArray[hash].addToStart(x);
}
}
public void output()
{
SLL tmp = new SLL();
SLL.Node temp = tmp.head;
for(int i = 0; i < size; i++)
{
if(temp == null)
//I think a new instance needs to be created
while(temp.getLink() != null)
{
System.out.println(i + temp.getData() + toString() + " ");
}
}
}
}
And this is the tester it should work with:
public class Tester{
// Have this method to display your name, instead.
static void displayName(){
System.out.println("Program written by Tony.\n");
}
// DO NOT MODIFY THE MAIN METHOD
public static void main(String[] args){
displayName();
Set set1 = new Set();
Set set2 = new Set();
set1.add(3);
set1.add(3);
set1.add(13);
set1.add(23);
set1.add(4);
set1.add(5);
set2.add(15);
set2.add(6);
set2.add(6);
System.out.println("Contents of set 'set1': ");
set1.output();
System.out.println("Contents of set 'set2': ");
set2.output();
System.out.println();
}
}
You need to iterate through the entries in your hash array, and for each non-null entry, iterate through the linked list:
public void output() {
for (int i = 0; i < hashArray.length; i++) {
if (hahArray[i] != null) {
hashArray[i].outputList();
}
}
}
In your for loop as below:
if(temp == null)
//I think a new instance needs to be created
while(temp.getLink() != null)
{
System.out.println(i + temp.getData() + toString() + " ");
}
You should be checking temp != null and you are not moving your node from one to other to traverse over each elements. So you should change it to:
while(temp != null) {
System.out.println(temp.getData() + " ");
temp = temp.getLink();
}
So changing the output( ) a bit to
public void output()
{
SLL tmp = new SLL();
SLL.Node temp = tmp.head;
for (SLL s : hashArray) {
System.out.println(toString() + " " + s);}
}
It still only prints "Programmed by Tony"
and "Contents of set 1:" "Contents of set 2: " without the actual set data?

Tree Print Tree Method

I am going over my old test from Data Structures, and I cannot figure out how to implement the printtree(int level) method in my Tree class. I am restricted to using this structure. I cannot figure out an implementation to use without root.right or root.left, this is very frustrating.
/*
Exam 2. Problem 2. 03/09/2012
*/
import java.util.List;
import java.util.ArrayList;
/**
A tree in which each node has an arbitrary number of children.
*/
public class Tree
{
private Node root;
class Node
{
public Object data;
public List<Node> children;
/**
Computes the size of the subtree whose root is this node.
#return the number of nodes in the subtree
*/
public int size()
{
int sum = 0;
for (Node child : children) { sum = sum + child.size(); }
return 1 + sum;
}
public int leaves() {
int count = 0;
for (Node child : children) {
if (child.size() == 1) {
count = count + 1;
} else {
count = count + child.leaves();
}
}
if (count == 0) {
count = count + 1;
}
return count;
}
public String printTree(int level) {
String S = "";
S += root.data + " (level:" + level + ") ";
if (root != null) {
return S;
}
if (root.children != null) {
S += root.printTree(level + 1);
}
return S;
}
}
/**
Constructs an empty tree.
*/
public Tree()
{
root = null;
}
/**
Constructs a tree with one node and no children.
#param rootData the data for the root
*/
public Tree(Object rootData)
{
root = new Node();
root.data = rootData;
root.children = new ArrayList<Node>();
}
/**
Adds a subtree as the last child of the root.
*/
public void addSubtree(Tree subtree)
{
root.children.add(subtree.root);
}
/**
Computes the size of this tree.
#return the number of nodes in the tree
*/
public int size()
{
if (root == null) { return 0; }
else { return root.size(); }
}
public int leaves() {
Node newNode = root;
if (root == null) { return 0; }
else { return root.leaves(); }
}
public String printTree() {
return root.children.printTree(0);
}
}
you just need to change 3 things:
Change root to this every where in the printTree(int level) method
The placement of if(this == null) should be checked before anything else
Use a for loop to print all of the children
public String printTree(int level) {
String S = "";
// notice the change to '=='
if (this == null)
return S;
S += this.data + " (level:" + level + ") ";
// notice the for loop
if( this.children != null)
for(Node child : this.children)
S += child.printTree(level + 1);
return S;
}

How to merge single node trees into large tree

I have a project which is to “Start with the tree.java program (Listing 8.1) and modify it to create a binary
tree from a string of letters (like A, B, and so on) entered by the user. Each
letter will be displayed in its own node. Construct the tree so that all the nodes
that contain letters are leaves. Parent nodes can contain some non-letter
symbol like +. Make sure that every parent node has exactly two children.
Don’t worry if the tree is unbalanced.” The book gives us a hint on how to begin. “One way to begin is by making an array of trees. (A group of unconnected trees
is called a forest.) Take each letter typed by the user and put it in a node. Take
each of these nodes and put it in a tree, where it will be the root. Now put all
these one-node trees in the array. Start by making a new tree with + at the root
and two of the one-node trees as its children. Then keep adding one-node trees
from the array to this larger tree. Don’t worry if it’s an unbalanced tree.”
import java.io.*;
import java.util.*;
class Node
{
public String iData; // data item (key)
public Node leftChild; // this node’s left child
public Node rightChild; // this node’s right child
public void displayNode() // display ourself
{
System.out.print('{');
System.out.print(iData);
System.out.print("} ");
}
} // end class Node
class Tree
{
private Node root; // first node of tree
public void setNode(Node newNode)
{root = newNode;}
public Node getNode()
{return root;}
// -------------------------------------------------------------
public Tree() // constructor
{ root = null; } // no nodes in tree yet
// -------------------------------------------------------------
public void traverse(int traverseType)
{
switch(traverseType)
{
case 1: System.out.print("nPreorder traversal: ");
preOrder(root);
break;
case 2: System.out.print("nInorder traversal: ");
inOrder(root);
break;
case 3: System.out.print("nPostorder traversal: ");
postOrder(root);
break;
}
System.out.println();
}
private void preOrder(Node localRoot)
{
if(localRoot != null)
{
System.out.print(localRoot.iData + " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
// -------------------------------------------------------------
private void inOrder(Node localRoot)
{
if(localRoot != null)
{
inOrder(localRoot.leftChild);
System.out.print(localRoot.iData + " ");
inOrder(localRoot.rightChild);
}
}
// -------------------------------------------------------------
private void postOrder(Node localRoot)
{
if(localRoot != null)
{
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
System.out.print(localRoot.iData + " ");
}
}
// -------------------------------------------------------------
public void displayTree()
{
Stack globalStack = new Stack();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println(
"......................................................");
while(isRowEmpty==false)
{
Stack localStack = new Stack();
isRowEmpty = true;
for(int j=0; j<nBlanks; j++)
System.out.print(' ');
while(globalStack.isEmpty()==false)
{
Node temp = (Node)globalStack.pop();
if(temp != null)
{
System.out.print(temp.iData);
localStack.push(temp.leftChild);
localStack.push(temp.rightChild);
if(temp.leftChild != null ||
temp.rightChild != null)
isRowEmpty = false;
}
else
{
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for(int j=0; j<nBlanks*2-2; j++)
System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while(localStack.isEmpty()==false)
globalStack.push( localStack.pop() );
} // end while isRowEmpty is false
System.out.println(
"......................................................");
} // end displayTree()
// -------------------------------------------------------------
}
public class Leaves
{
//function used to enter the single node trees into a larger tree
public static void enterLetters(Node localRoot, Tree[] nodeTree, int i)
{
if(localRoot != null && i == nodeTree.length)
{
if(nodeTree.length == i - 1)
{
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
else
{
Node plusNode = new Node();
plusNode.iData = "+";
localRoot.leftChild = plusNode;
localRoot.rightChild = nodeTree[i].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
}
}
public static void main(String[] args)
{
Tree[] forest = new Tree[10];
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
String letter;
forest[i] = new Tree();
System.out.println("Enter a letter: ");
letter = sc.nextLine();
Node newNode = new Node();
newNode.iData = letter;
forest[i].setNode(newNode);
}
Tree letterTree = new Tree();
Node firstNode = new Node();
firstNode.iData = "+";
letterTree.setNode(firstNode);
enterLetters(letterTree.getNode(), forest, 0);
letterTree.displayTree();
}
}
My problem is trying to get the array of single node trees into the larger tree. I tried making a recursive function but when I display the larger tree it only shows the first node and it is as if the function enterLeaves never did it’s job.
This can't be correct:
public static void enterLetters(Node localRoot, Tree[] nodeTree, int i) {
if (localRoot != null && i == nodeTree.length) {
if (nodeTree.length == i - 1) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
} else {
Node plusNode = new Node();
plusNode.iData = "+";
localRoot.leftChild = plusNode;
localRoot.rightChild = nodeTree[i].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
}
}
When you enter this method: localRoot != null, i == 0, and nodeTree.length==10
So the if statement is failing. I am guess the if statement should read:
if (localRoot != null && i < nodeTree.length)
Also, I am pretty sure your second if statement is incorrect also; I believe it should be.
if (nodeTree.length-2 == i) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
return;
}
Instead of:
if (nodeTree.length == i - 1) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
You want to stop when you have two Nodes left to process (nodeTree.length-2 == i) and after you do that you should return instead of entering the remaining letters.
Here's what I came up with that works:
Node.java
/** Represents a node in a binary tree data structure */
public class Node {
private char letter;
private Node leftChild;
private Node rightChild;
public Node(char letter) {
this.letter = letter;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
public Node getRightChild() {
return rightChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getLeftChild() {
return leftChild;
}
/** Returns a String representation of this node. */
#Override
public String toString() {
return "" + letter;
}
}
Tree.java
import java.util.Stack;
/**
* A binary tree
*/
public class Tree {
private Node root;
public void setRoot(Node root) {
this.root = root;
}
public void addToLeft(Node node) {
root.setLeftChild(node);
}
public void addToRight(Node node) {
root.setRightChild(node);
}
public Node getRoot() {
return root;
}
public void displayTree() {
Stack<Node> globalStack = new Stack<>();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println(
"......................................................");
while (!isRowEmpty) {
Stack<Node> localStack = new Stack<>();
isRowEmpty = true;
for (int j = 0; j < nBlanks; j++)
System.out.print(' ');
while (!globalStack.isEmpty()) {
Node temp = (Node) globalStack.pop();
if (temp != null) {
System.out.print(temp);
localStack.push(temp.getLeftChild());
localStack.push(temp.getRightChild());
if (temp.getLeftChild() != null ||
temp.getRightChild() != null)
isRowEmpty = false;
} else {
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for (int j = 0; j < nBlanks * 2 - 2; j++)
System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while (!localStack.isEmpty())
globalStack.push(localStack.pop());
} // end while isRowEmpty is false
System.out.println(
"......................................................");
}
}
Forest.java
/**
* A collection of OneNodeTrees combined together in one tree
*/
public class Forest {
private Tree[] forest;
private int forestIndex;
public Forest(int numTrees) {
forest = new Tree[numTrees];
forestIndex = 0;
}
public boolean add(Tree tree) {
if(forestIndex < forest.length) {
forest[forestIndex++] = tree;
return true;
} else {
return false;
}
}
public Tree createMainTree() {
Tree firstTree = new Tree();
firstTree.setRoot(new Node('+'));
firstTree.addToLeft(forest[0].getRoot());
firstTree.addToRight(forest[1].getRoot());
forest[1] = firstTree;
int mainTreeIndex = 0;
Tree tempTree;
for(mainTreeIndex = 2; mainTreeIndex < forest.length; mainTreeIndex++) {
tempTree = new Tree();
tempTree.setRoot(new Node('+'));
tempTree.addToLeft(forest[mainTreeIndex - 1].getRoot());
tempTree.addToRight(forest[mainTreeIndex].getRoot());
forest[mainTreeIndex] = tempTree;
}
return forest[mainTreeIndex - 1];
}
public static void main(String[] args) {
final int numberOfTrees = 6;
Forest forest = new Forest(numberOfTrees);
// Add characters starting from A which has ASCII value 65
int charLimit = 65 + numberOfTrees;
for(int i = 65; i < charLimit; i++) {
// Make new node.
Node newNode = new Node((char) i);
// Add that node to Tree as a root.
Tree newTree = new Tree();
newTree.setRoot(newNode);
// And add that one-node tree to forest(array)
forest.add(newTree);
}
Tree mainTree = forest.createMainTree();
mainTree.displayTree();
}
}
if(localRoot != null && i == nodeTree.length -1)
if you do not subtract one from node tree length you will have a duplicate child under the final parent node with 2 children

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