• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Binary Search Tree - Balanced (Java)

Status
Not open for further replies.
Level 2
Joined
Jun 13, 2011
Messages
15
Hi guys, specifically Dr.SuperGood, who is probably reading this.

I have a unbalanced binary tree and I show you the description of what I am doing. I just don't know how to make it "balanced" binary search tree. Please help.

BinarySearchTree
Code:
package util;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
 * A <code>BinarySearchTree</code>(BST) implements the <code>BinarySearchTreeADT</code>
 * interface, allowing <code>Comparable</code> objects to be inserted or
 * removed.  At all times, the tree is balanced (i.e. -1 <= balance factor <= 1
 * at every node in the tree).
 *
 * <p>The <code>BinarySearchTree</code> has two constructors:
 *   <ul>
 *     <li>a default constructor</li>
 *     <li>a constructor that has a <code>Comparable</code> item as a parameter</li>
 *   </ul></p>
 * <p>The public methods implement the <code>BinarySearchTreeADT</code> interface.</p>
 * <p>The implementation of this class is the lab 4 assignment for COMP 139 students.</p>
 */
public class BinarySearchTree implements BinarySearchTreeADT {
  private static final String INDENT = "                         ";
  private Node root;          // The root of the BST.
 
    /**
   * Create a blank String that consists of a set of indents.
   * @param indent the number of indents.
   * @return a String that contains 'indent' * INDENT.length() spaces.
   */
  private static String makeIndents(int indent) {
    String result = "";
    for (int i = 0; i < indent; i++) {
      result = result + BinarySearchTree.INDENT;
    }
    return result;
  }

  @Override
  public final void add(Comparable item) {
    this.root = addIterative(item, this.root);
  }

  private Node addIterative(Comparable item, Node n) {
    Node originalTree = n;

    // If the tree is empty, just create a new tree with one node.
    if (n == null) {
      Node newNode = new Node();
      newNode.item = item;
      return newNode;
    }

    // Find the insertion point.
    while (n != null) {
      int compare = item.compareTo(n.item);
      // Duplicate items are not allowed.
      if (compare == 0) throw new DuplicateElementException();

      // See if item belongs in the left subtree.
      if (compare < 0) {
        // If there is space then add a new node; otherwise,
        // keep looking for space.
        if (n.left == null) {
          n.left = new Node();
          n.left.item = item;
          //break;    // Node added, don't look any more.
          return balanceTree();
        }
        else n = n.left;
      }
      // The item must belong in the right subtree.
      else {
        // If there is space then add a new node; otherwise,
        // keep looking for space.
        if (n.right == null) {
          n.right = new Node();
          n.right.item = item;
          //break;    // Node added, don't look any more.
          return balanceTree();
        }
        else n = n.right;
      }
    }
    return originalTree;
  }
  
  private Node balanceTree(){
      if (root.getBalanceFactor()!= 2 && root.getBalanceFactor()!= 2) return root;
      Node newRootHere = new Node();
      if (root.getBalanceFactor() == -2 && root.left.getBalanceFactor()== -1) {
          newRootHere = rightRotation(root, root.left);
      }   
      if (root.getBalanceFactor()== 2 && root.right.getBalanceFactor()== 1) {
          newRootHere = leftRotation(root, root.right);
      }
      if (root.getBalanceFactor()== 2 && root.right.getBalanceFactor()== -1) {
      Node tempNode = rightRotation(root.right,root.right.left);
          newRootHere = leftRotation(root, tempNode);
      }   
      if (root.getBalanceFactor()== -2 && root.left.getBalanceFactor()== 1) {
          newRootHere = leftRotation(root, root.left);
      }
      if (root.getBalanceFactor()== 2 && root.right.getBalanceFactor()== 0) {
          newRootHere = leftRotation(root, root.right);
      }   
      if (root.getBalanceFactor()== -2 && root.left.getBalanceFactor()== 0) {
          newRootHere = rightRotation(root, root.left);
      }  
      return newRootHere;
  }
     
private Node leftRotation(Node oldRoot, Node newRoot){   
    Node newroot = newRoot;
    oldRoot.right = newroot.left;
    newroot.left = oldRoot;
    return newroot;
}

private Node rightRotation(Node oldRoot, Node newRoot){   
    Node newroot = newRoot;
    oldRoot.left = newroot.right;
    newroot.right = oldRoot;
    return newroot;
}
   
  @Override
  public Iterator<Comparable> iterator() /*throws ConcurrentModificationException,
                                                UnsupportedOperationException*/ {
    return new BinarySearchTreeIterator();
  }
   
  private final class BinarySearchTreeIterator implements Iterator<Comparable> {
        //private int root;

        private BinarySearchTreeIterator() {
        //this.root = 0;
        }


        @Override
        public boolean hasNext() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Comparable next() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
  }
  
  @Override
  public String printTree() {
    if (this.root == null) return "";
    return "\n" + printTree(this.root, 0);
  }

  /**
   * Create a string representation for a subtree of a binary search tree.
   * @param root the node at the root of the subtree.
   * @param level the node level (in the entire tree) for the root of this subtree.
   * @return a diagram, as a <code>String</code>, that represents this subtree.
   */  
  private String printTree(Node root, int level) {
    String result = "";
    if (root.right != null) {
      result = result + printTree(root.right, level + 1);
    }
    result = result + makeIndents(level) + root.item.toString() +
             "(" + root.getBalanceFactor() + ")\n";
    if (root.left != null) {
      result = result + printTree(root.left, level + 1);
    }
    return result;
  }

  @Override
  public void remove(Comparable item) {
    //this.root = removeIterativeAlmost(item, this.root);
    this.root = removeIterativeAlmost(item, this.root);      
  }

private Node removeIterativeAlmost(Comparable item, Node n) {
    // Find the node that contains the item to be removed and
    // the parent of that node.
    Node parent = null;
    Node toremove = n;
    while (toremove != null) {
      // Check to see if the item has been found.
      int compare = item.compareTo(toremove.item);
      if (compare == 0) break;
      
      // If not found, look in the appropriate subtree.
      parent = toremove;
      if (compare < 0) toremove = toremove.left;
      else toremove = toremove.right;
    }

    // Item was either found (toremove != null) or the item is not in the
    // tree (toremove == null).
    if (toremove == null) throw new NoSuchElementException();

    // If the node to be removed has no more than one child
    // then replace it with the other child.
    if (toremove.left == null) {
      replaceChildNodeInParent(parent, toremove, toremove.right);
      return n;
    }
    if (toremove.right == null) {
      replaceChildNodeInParent(parent, toremove, toremove.left);
      return n;
    }

    // The node to remove has two children.
    // 1. Find a replacemant value.
    // 2. Replace the value in the node to remove.
    // 3. Remove the node that contains the replacement value.
    Comparable largest = findLargest(toremove.left);
    toremove.item = largest;
    toremove.left = removeIterativeAlmost(largest, toremove.left);
    return n;
  }

  
  private void replaceChildNodeInParent(
          Node parent, Node currentchild, Node newchild) {

    if (parent == null) this.root = newchild;
    else if (parent.left == currentchild) parent.left = newchild;
         else parent.right = newchild;
  }

  /**
   * Find the largest value in the tree with 'n' as its root.
   * @param n the root of the tree.
   * @return the rightmost value in the tree.
   */  
  private Comparable findLargest(Node n) {
    while (n.right != null) {
      n = n.right;
    }
    return n.item;
  }

  /**
   * Find the smallest value in the tree with 'n' as its root.
   * @param n the root of the tree.
   * @return the leftmost value in the tree.
   */  
  private Comparable findSmallest(Node n) {
    while (n.left != null) {
      n = n.left;
    }
    return n.item;
  }

  /**
   * Define the data structure of a node in a balanced binary search tree.
   */
  private class Node {
    private Comparable item;    // The data item.
    private Node left;          // The root of the left subtree.
    private Node right;         // The root of the right subtree.
       
    /**
     * Determine the balance factor for this node.
     * @return the difference between the right height and the left height.
     */
    private int getBalanceFactor() {
      // Note: This code needs to be replaced.  It is here so that printTree()
      //       has a working getBalanceFactor() method to use.
      //return -999;
        int leftHeight = (left == null)?0:left.height();
        int rightHeight = (right == null)?0:right.height();
        return rightHeight - leftHeight;
    }

    private int height(){
        int leftHeight = (left == null)?0:left.height();
        int rightHeight = (right == null)?0:right.height();
        return 1 + Math.max(leftHeight, rightHeight);
   }
 }
}


BinarySearchTreeADT

Code:
package util;

import java.util.ConcurrentModificationException;
import java.util.Iterator;

/**
 * Defines a <code>BinarySearchTreeADT</code>.  A binary search tree is a
 * data structure that allows items to be added and removed and whose items
 * are organized into a binary tree structure such that, at any node 'x' in
 * the tree, all items in the left subtree at 'x' are less than the item at 'x'
 * and all items in the right subtree at 'x' are greater than the item at 'x'.
 * <p>Note: This definition means that duplicate items are <em>NOT</em>
 *    allowed in a binary search tree.</p>
 * @author Paul Rushton
 */
public interface BinarySearchTreeADT {

  /**
   * Add an item to the tree.
   * @param item the <code>Comparable</code> to be added.
   * @throws DuplicateElementException if an item to be added is equivalent
   * to one that is already in the tree.
   * 
   * Note: The tree is re-balanced after each <code>add()</code> operation.
   */
  public void add(Comparable item) throws DuplicateElementException;

  /**
   * Obtain an <code>Iterator<Comparable></code> for the tree.
   * @return an iterator that visits the items in the tree using an in-order
   * traversal.
   * @throws <code>ConcurrentModificationException</code> in the face of
   * concurrent modification.
   * @throws <code>UnsupportedOperationException</code> if the
   * <code>remove()</code> method is used.
   */
  public Iterator<Comparable> iterator() throws ConcurrentModificationException,
                                                UnsupportedOperationException;

  /**
   * Obtains a <code>String</code> representation for the tree.
   * @return A string that graphically shows the tree structure.
   * 
   * Note: If the <code>String</code> is printed then the output will be
   * in the shape of a tree with the root node at the left, the right subtree
   * above and to the right of the root, and the left subtree below and to
   * the right of the root. The balance factors for each node are shown in
   * parentheses beside the node.
   */
  public String printTree();

  /**
   * Remove an item from the tree.
   * @param item the <code>Comparable</code> to be removed.
   * 
   * Note: The tree is re-balanced after the <code>remove()</code> operation.
   */
  public void remove(Comparable item);
}


DuplicateElementException

Code:
package util;

/**
 * Defines the the condition of detecting a duplicate element in a collection.
 * @author D3158
 */
public class DuplicateElementException extends RuntimeException {
}


Lab4

Code:
public class BST {

  // Change this next line to your name.
  private static final String NAME = "D3158";

  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    BinarySearchTree tree = new BinarySearchTree();
    System.out.println("BBST: " + BST.NAME);

    System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
    tree.add("Eve");
    tree.add("Pam");
    tree.add("Zoe");
    tree.add("Cam");
    tree.add("Lee");
    tree.add("Joy");
    System.out.println("\nBinary search tree after add: Eve Pam Zoe Cam Lee Joy");
    System.out.print(tree.printTree());
    System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
    tree.add("Ivy");
    tree.add("Abe");
    tree.add("Fay");
    System.out.println("\nBinary search tree after add: Ivy Abe Fay");
    System.out.print(tree.printTree());
    System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
    System.out.println("\nIterator output\n");
    for (Iterator<Comparable> it = tree.iterator(); it.hasNext();) {
      System.out.print(it.next() + "  ");
    }
    System.out.println("\n\n= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
    tree.remove("Lee");
    tree.remove("Cam");
    tree.remove("Abe");
    System.out.println("\nBinary search tree after remove: Lee Cam Abe");
    System.out.print(tree.printTree());
    System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
  }
}

I have updated my BinarySearchTree.java. I think it's > BALANCED Binary Search Tree. However, I dont know how to make Iterator to work with Stacks. Can someone assist me please?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
You are after splaying the tree until it is ballenced.

The definition of ballenced that I see fit is that the height of the left and right nodes have a different no greater than 1.

The splay opperation you use must depend on which side is more or less ballenced.

A rough guess is that you start splaying around the place the new node was added or old node removed and move upwards towards the root.
 
Level 2
Joined
Jun 13, 2011
Messages
15
You are after splaying the tree until it is ballenced.

The definition of ballenced that I see fit is that the height of the left and right nodes have a different no greater than 1.

The splay opperation you use must depend on which side is more or less ballenced.

A rough guess is that you start splaying around the place the new node was added or old node removed and move upwards towards the root.

Yeah, I conquer. But I think I need an in order traversal method that talks back to the iterator method to make this work, I think?
 
Status
Not open for further replies.
Top