简体   繁体   English

低效二叉搜索树平衡算法

[英]Inefficient Binary Search Tree Balanced Algorithm

I am working on a project with Binary Search trees. 我正在使用Binary Search树进行项目。 This project requires me to create a method called isBalanced that checks if a binary search tree is balanced within a tolerance. 这个项目需要我创建一个名为isBalanced的方法,该方法检查二叉搜索树是否在公差范围内平衡。 I was able to figure out how to do this but it is dreadfully slow. 我能够弄清楚该怎么做,但是速度太慢了。 I was wondering if anyone had any tips to make it more efficient. 我想知道是否有人有提高其效率的提示。 By the way, .getLeftChild() and .getRightChild() have to return IllegalStateExceptions if the child is null. 顺便说一句,如果子项为null,则.getLeftChild()和.getRightChild()必须返回IllegalStateExceptions。 I would much prefer them to return null personally. 我更希望他们亲自返回null。

Here is a snippet of my code: 这是我的代码片段:

@Override
public <T> int getDepth(BinaryTreeNode<T> root) {
    return recDepth(root,0);
}

public <T> int recDepth(BinaryTreeNode<T> root,int depth) {
    int leftTree,rightTree;
    if(!root.hasLeftChild()&&!root.hasRightChild()) return depth;

    if(!root.hasLeftChild()) leftTree = 0;
    else                     leftTree = recDepth(root.getLeftChild(),depth+1);

    if(!root.hasRightChild()) rightTree = 0;
    else                      rightTree = recDepth(root.getRightChild(),depth+1);

    if(rightTree>leftTree) return rightTree; 
    else                   return leftTree;
}

@Override
public <T> boolean isBalanced(BinaryTreeNode<T> root, int tolerance) {
    if(tolerance<0) throw new IllegalArgumentException("Can't have negative tolerance");
    if(root==null) throw new NullPointerException();
    return recBalanced(root,tolerance);
}

public <T> boolean recBalanced(BinaryTreeNode<T> root, int tolerance){
    try{
    if(Math.abs(getDepth(root.getLeftChild())-getDepth(root.getLeftChild()))<=tolerance){
        return recBalanced(root.getLeftChild(),tolerance)&&recBalanced(root.getRightChild(),tolerance);
    }else return false;
    } catch (IllegalStateException e){
        if(root.hasLeftChild()&&getDepth(root.getLeftChild())>tolerance-1) return false;
        else if(root.hasRightChild()&&getDepth(root.getRightChild())>tolerance-1) return false;
        else return true;
    }
}

Thanks in advance for any help. 在此先感谢您的帮助。

Your problem of efficiency comes from the fact that you are traversing the same elements several times to compute the depth of a subtree and then the depth of its right and left subtrees. 您的效率问题来自于以下事实:您遍历相同的元素几次以计算子树的深度,然后计算其左右子树的深度。

When you have such overlapping problems that can be deduced by smaller problems, a bell must ring in your head : dynamic programming . 当您遇到这样的重叠问题(可以通过较小的问题来推论)时,必须警惕: 动态编程 You can compute a BinaryTreeNode<Integer> , that would contain the depth of each corresponding node (this tree would have the same shape as the original tree). 您可以计算BinaryTreeNode<Integer> ,它将包含每个对应节点的深度(此树的形状与原始树的形状相同)。 You would then only need to traverse this tree once to perform your computation, for a total time complexity of O(n) (a memory used of O(n) however). 然后,您只需要遍历该树一次即可执行计算,总时间复杂度为O(n) (但是使用的内存为O(n) )。

public BinaryTreeNode<Integer> computeDepthTree(BinaryTreeNode<T> bt) {
    return computeDepth(bt,0);
}

public BinaryTreeNode<Integer> computeDepthTree(BinaryTreeNode<T> bt, int depth) {
    BinaryTreeNode<Integer> result = new BinaryTreeNode<>(depth);
    if (bt.getLeftNode() != null)
        result.setLeftNode(computeDepthTree(bt.getLeftNode(),depth + 1));

    if (bt.getRightNode() != null)
        result.setRightNode(computeDepthTree(bt.getRightNode(),depth + 1));

    return result;
}

With this tree computed, when traversing a given node, you will get access to its depth in O(1) so the comparison of depth between child nodes of a same parent is going to be cheap ! 通过计算该树,遍历给定节点时,您将可以访问其在O(1)的深度,因此同一父节点的子节点之间的深度比较会很便宜!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM