在java中确定一个比率来查看二进制搜索树的平衡性。

问题描述 投票:0回答:1

我必须在实现层中使用任何一个公共方法来确定比率(根左边的节点数)(树的大小-1),这是一棵树平衡程度的指标。这些方法中的任何一个都是用来在应用层确定上面给出的比率的.这是我的代码。

public class BinarySearchTree<T extends Comparable<T>> 
             implements BSTInterface<T>
{
    protected BSTNode<T> root;   // reference to the root of this BST

    boolean found;   // used by remove

    // for traversals
    protected ArrayQueue<T> inOrderQ;
    protected ArrayQueue<T> preOrderQ;
    protected ArrayQueue<T> postOrderQ;

    protected LLStack<T> revOrderStack;

    T[] rebalanceArray;

    protected BSTNode<T> rebalanceRoot;   // reference to the root of rebalancing tree

    public BinarySearchTree() {
        root = null;
    }


    public void add (T element) {
        root = recAdd(element, root);
    }

    private BSTNode<T> recAdd(T element, BSTNode<T> tree) {
        if (tree == null) {
            tree = new BSTNode<T>(element);
        }
        else {
            if (element.compareTo(tree.getInfo()) <= 0) {
                tree.setLeft(recAdd(element, tree.getLeft()));  // add to left subtree

            }
            else {
                tree.setRight(recAdd(element, tree.getRight()));  // add to right subtree
            }
        }
        return tree;
    }


      public boolean remove (T element) {
          root = recRemove(element, root);
          return found;
      }

      private BSTNode<T> recRemove(T element, BSTNode<T> tree) {
          if (tree == null) {
              found = false;
          }
          else {
              if (element.compareTo(tree.getInfo()) < 0) {
                  tree.setLeft(recRemove(element, tree.getLeft()));
              }
              else {
                  if (element.compareTo(tree.getInfo()) > 0) {
                      tree.setRight(recRemove(element, tree.getRight()));
                  }
                  else {
                      tree = removeNode(tree);
                      found = true;
                  }
              }
          }
          return tree;
      }

      private BSTNode<T> removeNode(BSTNode<T> tree) {

          T payload;

          if (tree.getLeft() == null) {
              return tree.getRight();
          }
          else {
              if (tree.getRight() == null) {
                  return tree.getLeft();
              }
              else {
                  payload = getPredecessor(tree.getLeft());
                  tree.setInfo(payload);
                  tree.setLeft(recRemove(payload, tree.getLeft()));  
                  return tree;
              }
          }
      }

      private T getPredecessor(BSTNode<T> tree) {
          while (tree.getRight() != null) {
              tree = tree.getRight();
          }
          return tree.getInfo();
      }


      public int size() {
          return recSize(root);
      }

      private int recSize(BSTNode<T> tree) {
          if (tree == null) {
              return 0;
          }
          else {
              return recSize(tree.getLeft()) + recSize(tree.getRight()) + 1;
          }
      }


      // this implementation of a size operation demonstrates that
      // it is possible to visit all the nodes of the tree without recursion      
      public int size2() {
          int count = 0;
          if (root != null) {
              LLStack<BSTNode<T>> hold = new LLStack<BSTNode<T>>();
              BSTNode<T> currNode;
              hold.push(root);
              while (!hold.isEmpty()) {
                 currNode = hold.peek();
                 hold.pop();
                 count++;
                 if (currNode.getLeft() != null) {
                    hold.push(currNode.getLeft());
                 }
                 if (currNode.getRight() != null) {
                    hold.push(currNode.getRight());
                 }  
              }
          }
          return count;
      }


      public boolean isEmpty() {
          return (root == null);
      }


  public boolean contains (T element) {
    return recContains(element, root);
  }

  private boolean recContains(T element, BSTNode<T> tree) {
    if (tree == null) return false;
    else
        if (element.compareTo(tree.getInfo()) < 0)
            return recContains(element, tree.getLeft());  // search left subtree
        else
            if (element.compareTo(tree.getInfo()) > 0)
                return recContains(element, tree.getRight());  // search right subtree
            else
                return true;  // element is found!
  }


  public T get(T element) {
    return recGet(element, root);
  }

  private T recGet(T element, BSTNode<T> tree) {
      if (tree == null)
          return null;
      else
          if (element.compareTo(tree.getInfo()) < 0)
              return recGet(element, tree.getLeft());  // get from left subtree
          else
              if (element.compareTo(tree.getInfo()) > 0)
                  return recGet(element, tree.getRight());  // get from right subtree
              else
                  return tree.getInfo();  // element is found!
  }


  // populate inOrderQ with tree elements based on in-order traversal
  private void inOrder(BSTNode<T> tree) {
    if (tree != null) {
        inOrder(tree.getLeft());
        inOrderQ.enqueue(tree.getInfo());
        inOrder(tree.getRight());
    }
  }

  // populate preOrderQ with tree elements based on pre-order traversal
  private void preOrder(BSTNode<T> tree) {
      if (tree != null) {
          preOrderQ.enqueue(tree.getInfo());
          preOrder(tree.getLeft());
          preOrder(tree.getRight());
      }
  }

  // populate postOrderQ with tree elements based on post-order traversal
  private void postOrder(BSTNode<T> tree) {
      if (tree != null) {
          postOrder(tree.getLeft());
          postOrder(tree.getRight());
          postOrderQ.enqueue(tree.getInfo());
      }
  }


  // populate revOrderStack with tree elements in order to enable reverse order traversal
  private void revOrder(BSTNode<T> tree) {
    if (tree != null) {
        revOrder(tree.getLeft());
        revOrderStack.push(tree.getInfo());
        revOrder(tree.getRight());
    }
  }

  public int reset(TraversalType orderType) {
  // returns current number of nodes in the tree

    int numNodes = size();

    switch (orderType) {
       case INORDER :
           inOrderQ = new ArrayQueue<T>(numNodes);
           inOrder(root);
           break;

       case PREORDER :
           preOrderQ = new ArrayQueue<T>(numNodes);
           preOrder(root);
           break;

       case POSTORDER :
           postOrderQ = new ArrayQueue<T>(numNodes);
           postOrder(root);
           break;

       case REVORDER :
           revOrderStack = new LLStack<T>();
           revOrder(root);
           break;

    }

    return numNodes;
  }

  public T getNext (TraversalType orderType) {
  /*
   * preconditions
   *  - the BST is not empty
   *  - the BST has been reset for orderType
   *  - the BST has not been modified since the most recent reset
   *  - application code is responsible for not iterating beyond the end of the tree
   *
   * Returns the element at the current position on the BST for the specified traversal type
   * and advances the value of the current position. 
   *
   */
      switch (orderType) {
         case INORDER  : return inOrderQ.dequeue();
         case PREORDER : return preOrderQ.dequeue();
         case POSTORDER: return postOrderQ.dequeue();
         case REVORDER : return revOrderStack.pop();
                default: return null;  
      }
  }

  /*
   * PP#5 methods supporting new operations start here
   * 
   */

  public int treeHeight() {

      return recNodeHeight(root);

  }

  private int recNodeHeight(BSTNode<T> tree) {

      if (tree == null) {
          return -1;
      }

      if (tree.getLeft() == null && tree.getRight() == null) {
          return 0;
      }

      if (tree.getLeft() == null && tree.getRight() != null) {
          return 1 + recNodeHeight(tree.getRight());
      }

      if (tree.getLeft() != null && tree.getRight() == null) {
          return 1 + recNodeHeight(tree.getLeft());
      }

      // only possibility left is two children
      return 1 + Math.max(recNodeHeight(tree.getLeft()),recNodeHeight(tree.getRight()));
  }


  public void rebalance() {

      int size = reset(TraversalType.INORDER);

      rebalanceArray = (T[]) new Comparable[size];

      for (int i=0; i < size; i++) {
          rebalanceArray[i] = inOrderQ.dequeue();
      }

      rebalanceRoot = null;
      recRebalance(0, size-1);
      root = rebalanceRoot;
  }


  private void recRebalance(int first, int last) {

      if (first > last) {
          return;
      }
      else {
          if (first == last) {
              rebalanceRoot = recAdd(rebalanceArray[first], rebalanceRoot);
          }
          else {
              int mid = first + (last - first) / 2;
              rebalanceRoot = recAdd(rebalanceArray[mid], rebalanceRoot);
              recRebalance(first, mid-1);
              recRebalance(mid+1, last);
          }
      }
  }


  public int oobScore1() {
      return treeHeight() - (int)(Math.log(size()) / Math.log(2));
  }


  public int oobScore2() {
      return recOobScore2(root, 0);
  }

  private int recOobScore2(BSTNode<T> tree, int max) {

      if (tree == null) {
          return max;
      }

      if (tree.getLeft() == null && tree.getRight() == null) {
          return max;
      }

      if (tree.getLeft() != null && tree.getRight() == null) {
          return Math.max(max, recNodeHeight(tree));
      }

      if (tree.getLeft() == null && tree.getRight() != null) {
          return Math.max(max, recNodeHeight(tree));
      }

      // tree has both a left and right child:

      int heightLeft  = recNodeHeight(tree.getLeft());
      int heightRight = recNodeHeight(tree.getRight());
      max = Math.max(max, Math.abs(heightLeft - heightRight));

      int maxLeft = recOobScore2(tree.getLeft(), max);
      max = Math.max(max, maxLeft);

      int maxRight = recOobScore2(tree.getRight(), max);
      return Math.max(max, maxRight);

  }

}

我不知道该用哪种方法,因为它说的是树左边的节点数。而且我不认为有任何方法可以给我树左边的节点。我试过用size()-treeHeight(),但我不认为那有用。这是我在应用层面的代码。

public class Tree {

    public static void main(String[] args) {

        BinarySearchTree<String> bTree = new BinarySearchTree<String>();

        bTree.add("1");
        bTree.add("2");
        bTree.add("3");
        bTree.add("4");
        bTree.add("5");
        bTree.add("6");
        bTree.add("7");

        int size = abcTree.treeHeight() - 1;
        int leftNode = abcTree.size() - abcTree.oobScore2();
        double balanced = leftNode / size;

        for (int i = 0; i < size; i++ ) {
            if (i < leftNode) {
                //abcTree.rebalance();
                System.out.println(balanced);
                return;

             }
        }


    }

}
java binary-tree binary-search
1个回答
0
投票

把代码放在这里,因为我发现自己为了这个答案而改变了我开始的repl.it空间。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static java.util.Objects.isNull;

public class Main {

    public static void main(String[] args) {
        System.out.println("================================================");
        System.out.println("=======   Unbalanced Tree  =====================");
        System.out.println("================================================");
        printTreeData(getUnbalancedTree());
        System.out.println("================================================");
        System.out.println("=======   Balanced Tree  =======================");
        System.out.println("================================================");
        printTreeData(getBalancedTree());
    }

    private static BTree<Integer> getBalancedTree() {
        BTree<Integer> tree = new BTree<>();
        tree.add(15);
        tree.add(10);
        tree.add(16);
        tree.add(4);
        tree.add(2);
        tree.add(36);
        return tree;
    }

    private static BTree<Integer> getUnbalancedTree() {
        BTree<Integer> tree = new BTree<Integer>();
        tree.add(15);
        tree.add(2);
        tree.add(36);
        tree.add(12);
        tree.add(4);
        tree.add(10);
        tree.add(16);
        return tree;
    }

    private static void printTreeData(BTree<Integer> tree) {
        System.out.println("Depth: [" + tree.getDepth() + "] \nisBalanced [" + tree.isBalanced() + "]");
        System.out.println("Tree --> \n" + tree);

        List<Integer> values = tree.getValues();
        System.out.println("Values: " + values);
    }

}

class BTree<T extends Comparable<T>> {
    private BNode<T> root;

    public BNode<T> getRoot() {
        return root;
    }

    public void setRoot(BNode<T> root) {
        this.root = root;
    }

    public void add(T value) {
        if (isNull(root)) {
            root = new BNode<T>(value);
        } else {
            add(value, root);
        }
    }

    private void add(T value, BNode<T> node) {
        if (node.getValue().compareTo(value) >= 0) {
            if (isNull(node.getLeft())) {
                node.setLeft(new BNode<T>(value));
            } else {
                add(value, node.getLeft());
            }
        } else {
            if (isNull(node.getRight())) {
                node.setRight(new BNode<T>(value));
            } else {
                add(value, node.getRight());
            }
        }
    }

    public boolean isBalanced() {
        int diff = getNodeDepth(root.getLeft()) - getNodeDepth(root.getRight());
        diff = (diff < 0)? diff * -1: diff;
        return (diff <= 1);
    }

    public List<T> getValues() {
        return getValuesForNode(root);
    }

    private List<T> getValuesForNode(BNode<T> node) {
        if (isNull(node)) return new ArrayList<>();
        List<T> retList = new ArrayList<T>(getValuesForNode(node.getLeft()));
        retList.add(node.getValue());
        retList.addAll(getValuesForNode(node.getRight()));
        return retList;
    }

    public int getDepth() {
        return getNodeDepth(root);
    }

    private int getNodeDepth(BNode<T> node) {
        return (isNull(node)) ? 0 :
                (Math.max(getNodeDepth(node.getLeft()), getNodeDepth(node.getRight())) + 1);
    }

    private String getString(BNode<T> node, int level, String type) {
        return ((level > 0) ? "\\" : type) +
                IntStream.range(0, level).mapToObj(i -> "--").collect(Collectors.joining()) + " " +
                (isNull(node) ? "None" + type + "\n" :
                        node.getValue() + type + "\n"
                                + getString(node.getLeft(), level + 1, "[L]")
                                + getString(node.getRight(), level + 1, "[R]"));
    }

    @Override
    public String toString() {
        return getString(root, 0, "Root");
    }

}


class BNode<T> {
    T value;

    BNode<T> left;
    BNode<T> right;

    public BNode(T value) {
        this.value = value;
        left = null;
        right = null;
    }

    public T getValue() {
        return value;
    }

    public BNode<T> getLeft() {
        return left;
    }

    public void setLeft(BNode<T> left) {
        this.left = left;
    }

    public BNode<T> getRight() {
        return right;
    }

    public void setRight(BNode<T> right) {
        this.right = right;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.