How to print BinaryTree in Java? - java

public class BinaryNode<T> {
protected T data;
protected BinaryNode<T> left;
protected BinaryNode<T> right;
public BinaryNode(T element) {
if (element == null)
throw new IllegalArgumentException();
this.data = element;
left = null;
right = null;
}
public int height() {
int leftH = -1, rightH = -1;
if (left != null)
leftH = left.height();
if (right != null)
rightH = right.height();
return Math.max(leftH, rightH) + 1;
}
public int size() {
int leftS = 0, rightS = 0;
if (left != null)
leftS = left.size();
if (right != null)
rightS = right.size();
return leftS + rightS + 1;
}
private String spaces(int count){
String spaces="";
while(count>0){
spaces=spaces+" ";
count=count-1;
}
return spaces;
}
public String toString(){
String str="";
if(left!=null)
str=str+spaces(left.height())+left.toString(); //left
str=str+spaces(left.height()-1)+data.toString()+"\n";//root
if(right!=null)
str=str+spaces(right.height())+right.toString();//right
return str;
}
}
I need to build toString function in BinaryNode class. The method works so that if we print the string it returns we will get one print line per vertex in the tree. In this row, 2*d spaces will appear, where d is the depth of the vertex in the tree and then the information on the vertex will be printed (in the same row).
For example for the following BinarySearchTree (The examples in BinarySearchTree so it will be easier to understand how it needs to print):
BinarySearchTree t4 = new BinarySearchTree(c);
t4.insert(8);
t4.insert(7);
t4.insert(6);
t4.insert(5);
t4.insert(4);
t4.insert(3);
t4.insert(2);
t4.insert(1);
System.out.println("----------t4:----------\n" + t4);
toString need to print:
----------t4:----------
1
2
3
4
5
6
7
8
I wrote above the code that I create but it's doesn't working, the problem is that I know why it doesn't working but I don't know how to fix it.
Basically, I don't know to do it.
Appreciate any help.

Got the solution for those who need it:
private String spaces(int count){
String spaces="";
while(count>0){
spaces=spaces+" ";
count=count-1;
}
return spaces;
}
private String toString(int depth){
String str="";
if(left!=null)
{
str=str+left.toString(depth+1);
}
str=str+spaces(depth)+data.toString()+"\n";
if(right!=null)
{
str=str+right.toString(depth+1);
}
return str;
}
private String toString(String str){
if(left!=null)
str=str+left.toString(" ");
str=str+data.toString()+"\n";
if(right!=null)
str=str+right.toString(" ");
return str;
}

Related

Why am I getting an incorrect answer while trying to find the closest value in a BST given a target value?

There is only one difference between the correct answer and my answer, and that is, I am traversing the entire tree instead of comparing the target with the node value and eliminating one-half of the tree in each recursion. Please help me with the explanation. Thanks.
My code:
import java.util.*;
class Program {
public static int findClosestValueInBst(BST tree, int target) {
//int closest = Integer.MAX_VALUE;
// int val = 0;
int vl = findClosestValueInBst1(tree, target, tree.value);
return vl;
}
public static int findClosestValueInBst1(BST tree, int target, int val) {
// System.out.println((closest + " " + Math.abs(tree.value - target)));
//c = closest;
if(( Math.abs(target - tree.value)) < ( Math.abs(target - val))){
System.out.println(val);
val = tree.value;
}
if(tree.left != null){
return findClosestValueInBst1(tree.left, target, val);
}
if(tree.right != null){
return findClosestValueInBst1(tree.right, target, val);
}
return val;
}
static class BST {
public int value;
public BST left;
public BST right;
public BST(int value) {
this.value = value;
}
}
}
Question tree- Root =10,
Nodes-> [10,15,22,13,14,5,5,2,1],
Target: 12,
My output: 10,
Correct answer: 13,
import java.util.*;
class Program {
public static int findClosestValueInBst(BST tree, int target) {
//int closest = Integer.MAX_VALUE;
// int val = 0;
int vl = findClosestValueInBst1(tree, target, tree.value);
return vl;
}
public static int findClosestValueInBst1(BST tree, int target, int val) {
// System.out.println((closest + " " + Math.abs(tree.value - target)));
//c = closest;
if(( Math.abs(target - tree.value)) < ( Math.abs(target - val))){
System.out.println(val);
val = tree.value;
}
if( target < tree.value && tree.left != null){
return findClosestValueInBst1(tree.left, target, val);
} else
if(target > tree.value && tree.right != null){
return findClosestValueInBst1(tree.right, target, val);
} else
return val;
}
static class BST {
public int value;
public BST left;
public BST right;
public BST(int value) {
this.value = value;
}
}
}
The tree looks like this:
10
/\
5 15
/ /\
2 13 22
/ \
1 14
Your code is not actually traversing the whole tree. This code:
if(tree.left != null){
return findClosestValueInBst1(tree.left, target, val);
}
if(tree.right != null){
return findClosestValueInBst1(tree.right, target, val);
}
return val;
checks the left subtree if it exists (and ignores the right subtree). Otherwise, check the right subtree if it exists. Otherwise stop the recursion. This is because once you reach a return statement, the entire method stops there, and the lines after that do not get executed.
So your code always prefers the left subtree without taking into account what number the node actually stores. So right off the bat, you went to the wrong direction - you are looking for 13, and the current node is 10, a closer value is gotta be bigger than 10, i.e. in the right subtree.
An implementation that actually traverses the whole tree would be something like:
public static int findClosestValueInBst(BST tree, int target) { // no need for the val argument!
int leftClosest = tree.value;
int rightClosest = tree.value;
if(tree.left != null){
leftClosest = findClosestValueInBst1(tree.left, target);
}
if(tree.right != null){
rightClosest = findClosestValueInBst1(tree.right, target);
}
if (target - leftClosest < rightClosest - target) {
return leftClosest;
} else {
return rightClosest;
}
}
But why bother when you can do it more quickly? :)

Get Words out of a Trie Data Structure

i have the following Trie Data Structure:
public class CDictionary implements IDictionary {
private static final int N = 'z' -'a'+1;
private static class Node {
private boolean end = false;
private Node[] next = new Node[N];
}
private int size = 0;
private Node root = new Node();
#Override
public boolean contains(String word) {
Node node = this.contains(root,word,0);
if (node == null) {
return false;
}
return node.end;
}
private Node contains(Node node, String str, int d) {
if (node == null) return null;
if (d == str.length()) return node;
char c = str.charAt(d);
return contains(node.next[c-'a'], str, d+1);
}
#Override
public void insert(String word) {
this.root = insert(this.root, word, 0);
this.size++;
}
private Node insert(Node node, String str, int d) {
if (node == null) node = new Node();
if (d == str.length()) {
node.end = true;
return node;
}
char c = str.charAt(d);
node.next[c-'a'] = this.insert(node.next[c-'a'], str, d+1);
return node;
}
#Override
public int size() {
return size;
}
The Trie is filled with some words like
for, the, each, home, is, it, egg, red...
Now i need a function to get all Words with a specific length for example the length 3
public List<String> getWords(int lenght) {
}
With the Words mentioned above it should return a list with the words
for,the,egg,red
The Problem is how can i restore these words out of the Trie Structur?
You need to recurse through your structure to a maximum depth of N (in this case 3)
You could do this by adding a couple of methods to your dictionary...
public List<String> findWordsOfLength(int length) {
// Create new empty list for results
List<String> results = new ArrayList<>();
// Start at the root node (level 0)...
findWordsOfLength(root, "", 0, length, results);
// Return the results
return results;
}
public void findWordsOfLength(Node node, String wordSoFar, int depth, int maxDepth, List<String> results) {
// Go through each "child" of this node
for(int k = 0; k < node.next.length; k++) {
Node child = node.next[k];
// If this child exists...
if(child != null) {
// Work out the letter that this child represents
char letter = 'a' + k;
// If we have reached "maxDepth" letters...
if(depth == maxDepth) {
// Add this letter to the end of the word so far and then add the word to the results list
results.add(wordSoFar + letter);
} else {
// Otherwise recurse to the next level
findWordsOfLength(child, wordSoDar + letter, depth + 1, maxDepth, results);
}
}
}
}
(I have not compiled / tested this, but it should give you an idea of what you need to do)
Hope this helps.

Recursively find nth to last element in linked list

I'm practicing basic data structure stuff and I'm having some difficulties with recursion. I understand how to do this through iteration but all of my attempts to return the nth node from the last of a linked list via recursion result in null. This is my code so far:
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
else{
findnthToLastRecursion(node.next(), pos);
if(++i == pos) return node;
return null;
}
Can anyone help me understand where I'm going wrong here?
This is my iterative solution which works fine, but I'd really like to know how to translate this into recursion:
public static Link.Node findnthToLast(Link.Node head, int n) {
if (n < 1 || head == null) {
return null;
}
Link.Node pntr1 = head, pntr2 = head;
for (int i = 0; i < n - 1; i++) {
if (pntr2 == null) {
return null;
} else {
pntr2 = pntr2.next();
}
}
while (pntr2.next() != null) {
pntr1 = pntr1.next();
pntr2 = pntr2.next();
}
return pntr1;
}
You need to go to the end and then count your way back, make sure to pass back the node each time its passed back. I like one return point
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
Link.Node result = node;
if(node != null) {
result = findnthToLastRecursion(node.next, pos);
if(i++ == pos){
result = node;
}
}
return result;
}
Working example outputs 7 as 2 away from the 9th and last node:
public class NodeTest {
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
/**
* #param args
*/
public static void main(String[] args) {
Node first = null;
Node prev = null;
for (int i = 0; i < 10; i++) {
Node current = new Node(prev, Integer.toString(i),null);
if(i==0){
first = current;
}
if(prev != null){
prev.next = current;
}
prev = current;
}
System.out.println( findnthToLastRecursion(first,2).item);
}
public static int i = 0;
public static Node findnthToLastRecursion(Node node, int pos) {
Node result = node;
if (node != null) {
result = findnthToLastRecursion(node.next, pos);
if (i++ == pos) {
result = node;
}
}
return result;
}
}
No need for static variables.
public class List {
private Node head = null;
// [...] Other methods
public Node findNthLastRecursive(int nth) {
if (nth <= 0) return null;
return this.findNthLastRecursive(this.head, nth, new int[] {0});
}
private Node findNthLastRecursive(Node p, int nth, int[] pos) {
if (p == null) {
return null;
}
Node n = findNthLastRecursive(p.next, nth, pos);
pos[0]++;
if (pos[0] == nth) {
n = p;
}
return n;
}
}
You can do this a couple of ways:
recurse through the list once to find the list length, then write a recursive method to return the kth element (a much easier problem).
use an auxiliary structure to hold the result plus the remaining length; this essentially replaces the two recursions of the first option with a single recursion:
static class State {
Link.Node result;
int trailingLength;
}
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
State state = new State();
findnthToLastRecursion(node, pos, state);
return state.result;
}
private static void findnthToLastRecursion(Link.Node node, int pos, State state) {
if (node == null) {
state.trailingLength = 0;
} else {
findnthToLastRecursion(node.next(), state);
if (pos == state.trailingLength) {
state.result = node;
}
++state.trailingLength;
}
}
I misunderstood the question. Here is an answer based on your iterative solution:
public static Link.Node findnthToLast(Link.Node head, int n) {
return findnthToLastHelper(head, head, n);
}
private static Link.Node findnthToLastHelper(Link.Node head, Link.Node end, int n) {
if ( end == null ) {
return ( n > 0 ? null : head);
} elseif ( n > 0 ) {
return findnthToLastHelper(head, end.next(), n-1);
} else {
return findnthToLastHelper(head.next(), end.next(), 0);
}
}
actually you don't need to have public static int i = 0; . for utill method the pos is :
pos = linked list length - pos from last + 1
public static Node findnthToLastRecursion(Node node, int pos) {
if(node ==null){ //if null then return null
return null;
}
int length = length(node);//find the length of the liked list
if(length < pos){
return null;
}
else{
return utill(node, length - pos + 1);
}
}
private static int length(Node n){//method which finds the length of the linked list
if(n==null){
return 0;
}
int count = 0;
while(n!=null){
count++;
n=n.next;
}
return count;
}
private static Node utill(Node node, int pos) {
if(node == null) {
return null;
}
if(pos ==1){
return node;
}
else{
return utill(node.next, pos-1);
}
}
Here node.next is the next node. I am directly accessing the next node rather than calling the next() method. Hope it helps.
This cheats (slightly) but it looks good.
public class Test {
List<String> list = new ArrayList<> (Arrays.asList("Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"));
public static String findNthToLastUsingRecursionCheatingALittle(List<String> list, int n) {
int s = list.size();
return s > n
// Go deeper!
? findNthToLastUsingRecursionCheatingALittle(list.subList(1, list.size()), n)
// Found it.
: s == n ? list.get(0)
// Too far.
: null;
}
public void test() {
System.out.println(findNthToLastUsingRecursionCheating(list,3));
}
public static void main(String args[]) {
new Test().test();
}
}
It prints:
Eight
which I suppose is correct.
I have use List instead of some LinkedList variant because I do not want to reinvent anything.
int nthNode(struct Node* head, int n)
{
if (head == NULL)
return 0;
else {
int i;
i = nthNode(head->left, n) + 1;
printf("=%d,%d,%d\n", head->data,i,n);
if (i == n)
printf("%d\n", head->data);
}
}
public class NthElementFromLast {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
Stream.of("A","B","C","D","E").forEach(s -> list.add(s));
System.out.println(list);
System.out.println(getNthElementFromLast(list,2));
}
private static String getNthElementFromLast(List list, int positionFromLast) {
String current = (String) list.get(0);
int index = positionFromLast;
ListIterator<String> listIterator = list.listIterator();
while(positionFromLast>0 && listIterator.hasNext()){
positionFromLast--;
current = listIterator.next();
}
if(positionFromLast != 0) {
return null;
}
String nthFromLast = null;
ListIterator<String> stringListIterator = list.listIterator();
while(listIterator.hasNext()) {
current = listIterator.next();
nthFromLast = stringListIterator.next();
}
return nthFromLast;
}
}
This will find Nth element from last.
My approach is simple and straight,you can change the array size depending upon your requirement:
int pos_from_tail(node *k,int n)
{ static int count=0,a[100];
if(!k) return -1;
else
pos_from_tail(k->next,n);
a[count++]=k->data;
return a[n];
}
You'll have make slight changes in the code:
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
else{
**Link.Node temp = findnthToLastRecursion(node.next(), pos);
if(temp!=null)
return temp;**
if(++i == pos) return node;
return null;
}
}

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