堆栈溢出二进制搜索树平衡

时间:2014-09-30 08:36:34

标签: java binary-search-tree stack-overflow

运行此程序时,我在二叉搜索树中添加了大约3或4个值。在树中添加值后,我使用校验余额法查看不平衡是否为2或更大。一旦它达到2或更高,我使用balancebst方法来平衡它。在使用balance bst方法之后,我再次检查节点平衡级别以确保它已减少到至少1.由于某种原因,在添加几个值之后我的balancebst方法导致堆栈溢出。有谁知道为什么?这是一个非常长的类,但是balancebst方法和主要方法更接近底部。

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JOptionPane;






public class TestBST<E extends Comparable<E>> {
  final double K = 1.3;
  int height = 0;  
  protected TreeNode<E> root;
  protected int size = 0;

  /** Create a default binary tree */
  public TestBST() {
  }

  /** Create a binary tree from an array of objects */
  public TestBST(E[] objects) {
    for (int i = 0; i < objects.length; i++)
      insert(objects[i]);
  }

  /** Returns true if the element is in the tree */
  public boolean search(E e) {
    TreeNode<E> current = root; // Start from the root

    while (current != null) {
      if (e.compareTo(current.element) < 0) {
        current = current.left;
      }
      else if (e.compareTo(current.element) > 0) {
        current = current.right;
      }
      else // element matches current.element
        return true; // Element is found
    }

    return false;
  }

  /** Insert element o into the binary tree
   * Return true if the element is inserted successfully */
  public boolean insert(E e) {
    if (root == null)
      root = createNewNode(e); // Create a new root
    else {
      // Locate the parent node
      TreeNode<E> parent = null;
      TreeNode<E> current = root;
      while (current != null)
        if (e.compareTo(current.element) < 0) {
          parent = current;
          current = current.left;
        }
        else if (e.compareTo(current.element) > 0) {
          parent = current;
          current = current.right;
        }
        else
          return false; // Duplicate node not inserted

      // Create the new node and attach it to the parent node
      if (e.compareTo(parent.element) < 0)
        parent.left = createNewNode(e);
      else
        parent.right = createNewNode(e);
    }

    size++;
    return true; // Element inserted
  }

  protected TreeNode<E> createNewNode(E e) {
    return new TreeNode<E>(e);
  }

  /** Inorder traversal from the root*/
  public void inorder() {
    inorder(root);
  }

  /** Inorder traversal from a subtree */
  protected void inorder(TreeNode<E> root) {
    if (root == null) return;
    inorder(root.left);
    System.out.print(root.element + " ");
    inorder(root.right);
  }

  /** Postorder traversal from the root */
  public void postorder() {
    postorder(root);
  }

  /** Postorder traversal from a subtree */
  protected void postorder(TreeNode<E> root) {
    if (root == null) return;
    postorder(root.left);
    postorder(root.right);
    System.out.print(root.element + " ");
  }

  /** Preorder traversal from the root */
  public void preorder() {
    preorder(root);
  }

  /** Preorder traversal from a subtree */
  protected void preorder(TreeNode<E> root) {
    if (root == null) return;
    System.out.print(root.element + " ");
    preorder(root.left);
    preorder(root.right);
  }

  /** This inner class is static, because it does not access 
      any instance members defined in its outer class */
  public static class TreeNode<E extends Comparable<E>> {
    protected E element;
    protected TreeNode<E> left;
    protected TreeNode<E> right;

    public TreeNode(E e) {
      element = e;
    }
  }

  /** Get the number of nodes in the tree */
  public int getSize() {
    return size;
  }

  /** Returns the root of the tree */
  public TreeNode<E> getRoot() {
    return root;
  }

  /** Returns a path from the root leading to the specified element */
  public java.util.ArrayList<TreeNode<E>> path(E e) {
    java.util.ArrayList<TreeNode<E>> list =
      new java.util.ArrayList<TreeNode<E>>();
    TreeNode<E> current = root; // Start from the root

    while (current != null) {
      list.add(current); // Add the node to the list
      if (e.compareTo(current.element) < 0) {
        current = current.left;
      }
      else if (e.compareTo(current.element) > 0) {
        current = current.right;
      }
      else
        break;
    }

    return list; // Return an array of nodes
  }

  /** Delete an element from the binary tree.
   * Return true if the element is deleted successfully
   * Return false if the element is not in the tree */
  public boolean delete(E e) {
    // Locate the node to be deleted and also locate its parent node
    TreeNode<E> parent = null;
    TreeNode<E> current = root;
    while (current != null) {
      if (e.compareTo(current.element) < 0) {
        parent = current;
        current = current.left;
      }
      else if (e.compareTo(current.element) > 0) {
        parent = current;
        current = current.right;
      }
      else
        break; // Element is in the tree pointed at by current
    }

    if (current == null)
      return false; // Element is not in the tree

    // Case 1: current has no left children
    if (current.left == null) {
      // Connect the parent with the right child of the current node
      if (parent == null) {
        root = current.right;
      }
      else {
        if (e.compareTo(parent.element) < 0)
          parent.left = current.right;
        else
          parent.right = current.right;
      }
    }
    else {
      // Case 2: The current node has a left child
      // Locate the rightmost node in the left subtree of
      // the current node and also its parent
      TreeNode<E> parentOfRightMost = current;
      TreeNode<E> rightMost = current.left;

      while (rightMost.right != null) {
        parentOfRightMost = rightMost;
        rightMost = rightMost.right; // Keep going to the right
      }

      // Replace the element in current by the element in rightMost
      current.element = rightMost.element;

      // Eliminate rightmost node
      if (parentOfRightMost.right == rightMost)
        parentOfRightMost.right = rightMost.left;
      else
        // Special case: parentOfRightMost == current
        parentOfRightMost.left = rightMost.left;     
    }

    size--;
    return true; // Element inserted
  }

  /** Obtain an iterator. Use inorder. */
  public java.util.Iterator<E> iterator() {
    return new InorderIterator();
  }

  // Inner class InorderIterator
  private class InorderIterator implements java.util.Iterator<E> {
    // Store the elements in a list
    private java.util.ArrayList<E> list =
      new java.util.ArrayList<E>();
    private int current = 0; // Point to the current element in list

    public InorderIterator() {
      inorder(); // Traverse binary tree and store elements in list
    }

    /** Inorder traversal from the root*/
    private void inorder() {
      inorder(root);
    }

    /** Inorder traversal from a subtree */
    private void inorder(TreeNode<E> root) {
      if (root == null)return;
      inorder(root.left);
      list.add(root.element);
      inorder(root.right);
    }

    /** More elements for traversing? */
    public boolean hasNext() {
      if (current < list.size())
        return true;

      return false;
    }

    /** Get the current element and move to the next */
    public E next() {
      return list.get(current++);
    }

    /** Remove the current element */
    public void remove() {
      delete(list.get(current)); // Delete the current element
      list.clear(); // Clear the list
      inorder(); // Rebuild the list
    }
  }

  /** Remove all elements from the tree */
  public void clear() {
    root = null;
    size = 0;
  }




    public int treeHeight(){
        return treeHeight(root);
    }

    private int treeHeight(TreeNode root){
        return treeHeight(root, 0);
    }

    private int treeHeight(TreeNode root, int length){
        if (root == null)
            return length;

        return Math.max(    treeHeight(root.left, length + 1),
                            treeHeight(root.right, length + 1));
    }

    public int numberOfNodesAtLevel(int level){
     return   numberOfNodesAtLevel(root, level);
    }

    private int numberOfNodesAtLevel(TreeNode root, int level){
        if (root == null){
            return 0;
        }
        if (level == 0){
            return 1;
        }

        return  numberOfNodesAtLevel(root.left, level - 1) +
                numberOfNodesAtLevel(root.right, level - 1);
    }

    public int nodeBalanceLevel(){
    return  nodeBalanceLevel(root);
    }

    private int nodeBalanceLevel(TreeNode root){
        if (root == null)
            return 0;

        return Math.abs(    treeHeight(root.left)
                            - treeHeight(root.right));
    }

    private double minAceLevelNodes(int power, double totalLevels){
        double sum = 0;
        if (power < totalLevels){
        sum = Math.pow(2, power) - 1;
        return sum;}

        sum = getSize() - (Math.pow(2,  (Math.floor( totalLevels) - 1 ))) -1 ;
        return sum;
    }


public double calculateAce(){
    double sum = 0; 
    int level;
    for ( level = 0; level < (int) treeHeight() ; level++){
        sum += numberOfNodesAtLevel(level) * (level + 1);
    }
    double ace = sum/ this.size;
    return ace;

}
  public double calculateMinAce(){
      double sum = 0; 
        double totalLevels = Math.floor( Math.log(getSize()+1)/Math.log(2));
        int level;
        for ( level = 0; level < totalLevels ; level++){
            sum += minAceLevelNodes(level, totalLevels) * (level + 1);
        }
        double ace = sum/ this.size;
        return ace;
  }

  public double calculateMaxAce(){
      double sum = 0; 
        int level;
        for ( level = 0; level < (int) getSize() ; level++){
            sum += (level + 1);
        }
        double ace = sum/ this.size;
        return ace;
  }

  public boolean needsBalancing(){
    if ( calculateAce() > calculateMinAce() * K ){
      return true;}
    return false;

  }

  public boolean balanceBST(){
      if (root == null){
          return false;
      }

      int right = treeHeight(root.right);
      int left = treeHeight(root.left);

      if (nodeBalanceLevel(root) > 1){

                if (right - left > 1){
                    this.balanceRight();
        }
        if ( left - right > 1){
        this.balanceLeft(); 
        }
        return balanceBST();  

      }

    return true;

  }

  private void balanceRight() {
      TreeNode oldRoot = root;     // Save the current root (1)
      if (root.right != null) {    // Can this ever happen? (*)
        root = root.right;         // Setting the new root  (2)
      }
      if (oldRoot.left != null) {  // Adjust the left sub tree
        oldRoot.right = root.left; // Assign the left sub tree to the previous root right tree (3)
        root.left = oldRoot;       // Assign to the new left tree the prevouis left tree (4)
      }
    }

  private void balanceLeft() {
      TreeNode oldRoot = root;     // Save the current root (1)
      if (root.left != null) {    // Can this ever happen? (*)
        root = root.left;         // Setting the new root  (2)
      }
      if (oldRoot.right != null) {  // Adjust the left sub tree
        oldRoot.left = root.right; // Assign the left sub tree to the previous root right tree (3)
        root.right = oldRoot;       // Assign to the new left tree the prevouis left tree (4)
      }
    }

  public static void main(String[] args){

     File input = new File("BSTINPUT.txt");
     try {

        Scanner reader = new Scanner(input);
        ArrayList <String> valuePasser = new ArrayList <String>();
        String [] tempStorage;
    while (reader.hasNext()){
        String line = reader.nextLine();
        tempStorage =(line.split(";"));
      for (int i = 0; i< tempStorage.length; i++){
        valuePasser.add( tempStorage[i]);
      }
    }

    String[] tempHold = new String[valuePasser.size()];
    for (int i = 0; i< valuePasser.size(); i++){
        tempHold[i] = valuePasser.get(i);
    }

    TestBST <String> bst = new TestBST<String> (tempHold);
    int actionChoice = 12;
    do{
        try{

        actionChoice = Integer.parseInt( JOptionPane.showInputDialog("Please choose action: \n "
                + "(0) Exit program\n (1) In-order tree traversal\n (2) Pre-order tree traversal\n (3) CalculateACE\n"
                + "(4) CalculateMinAce\n (5) CalculateMaxACE\n (6) NumberOfNodesAllLevels\n  (7) TreeHeight\n (8) NodeBalanceLevel\n "
                + "(9) NeedsBalancing\n (10) BalanceBST\n (11) insert value\n" ));}
        catch (NumberFormatException e){
            JOptionPane.showMessageDialog(null, "Sorry, program only takes integer values between 0 and 10. Please restart program");
            System.exit(1);
        }

        if (actionChoice < 0 || actionChoice > 11){
            JOptionPane.showMessageDialog(null, "Sorry, program only takes integer values between 0 and 10. please restart program");
            System.exit(1);
        }

        if (actionChoice ==1){
            System.out.println(" In-order tree values: ");
          bst.inorder();
          System.out.println(" ");
        }

       if (actionChoice ==2){
           System.out.println("pre-order tree values: ");
          bst.preorder();   
          System.out.println(" ");
        }

       if (actionChoice ==3){
           System.out.println( "Tree ACE value : " + bst.calculateAce());
          System.out.println(" ");
       }
       if (actionChoice ==4){
           System.out.println( "Tree minACE value : " + bst.calculateMinAce());
           System.out.println(" ");
       }
       if (actionChoice ==5){
           System.out.println( "Tree maxACE value : " + bst.calculateMaxAce());
           System.out.println(" ");
       }
       if (actionChoice ==6){
        System.out.println(" The number of nodes at all levels of the tree are:");
        for (int i = 0; i< bst.treeHeight(); i++){
            System.out.println("Number of nodes at level: " + i);
            System.out.println(bst.numberOfNodesAtLevel(i));
        }
        System.out.println(" ");
       }
       if (actionChoice ==7){
         System.out.println(" Current tree height: "+ bst.treeHeight());
         System.out.println(" ");
       }
       if (actionChoice ==8){
           System.out.println(" Node Balance Level: "+ bst.nodeBalanceLevel());
           System.out.println(" ");
       }
       if (actionChoice ==9){
           System.out.println(" Tree needs balancing?: "+ bst.needsBalancing());
           System.out.println(" ");
       }
       if (actionChoice ==10){
           System.out.println(" Balancing BST: "+ bst.balanceBST());
           System.out.println(" ");
       }
       if (actionChoice ==11){
         bst.insert(  JOptionPane.showInputDialog("Input integer to be added to tree: "));
           System.out.println(" ");
       }



    }while (actionChoice != 0);




    } catch (FileNotFoundException e) {
        System.out.println("File not found. Please connect BSTINPUT.txt file and restart program.");
    }


  }
}

0 个答案:

没有答案