Java 低效的二叉搜索树平衡算法

Java 低效的二叉搜索树平衡算法,java,binary-tree,binary-search-tree,Java,Binary Tree,Binary Search Tree,我正在做一个二叉搜索树的项目。这个项目需要我创建一个名为isBalanced的方法,该方法检查二进制搜索树是否在容差范围内平衡。我能想出如何做到这一点,但它是可怕的缓慢。我想知道是否有人能给我一些建议来提高效率。顺便说一下,.getLeftChild()和.getRightChild()必须在子项为null时返回IllegalStateCeptions。我更希望他们亲自返回null 以下是我的代码片段: @Override public <T> int getDepth(Binary

我正在做一个二叉搜索树的项目。这个项目需要我创建一个名为isBalanced的方法,该方法检查二进制搜索树是否在容差范围内平衡。我能想出如何做到这一点,但它是可怕的缓慢。我想知道是否有人能给我一些建议来提高效率。顺便说一下,.getLeftChild()和.getRightChild()必须在子项为null时返回IllegalStateCeptions。我更希望他们亲自返回null

以下是我的代码片段:

@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;
    }
}
@覆盖
public int getDepth(二进制树节点根){
返回深度(根,0);
}
公共int-recDepth(二进制树节点根,int-depth){
int leftTree,rightree;
if(!root.hasleetchild()&&!root.hasleetchild())返回深度;
如果(!root.hasleeftchild())leftTree=0;
else leftTree=recDepth(root.getLeftChild(),depth+1);
如果(!root.hasRightChild())rightTree=0;
else rightTree=recDepth(root.getRightChild(),深度+1);
如果(rightTree>leftTree)返回rightTree;
否则返回左树;
}
@凌驾
公共布尔值是平衡的(二进制树节点根,整数容差){
如果(公差公差-1)返回false;
否则返回true;
}
}

提前感谢您的帮助。

您的效率问题来自这样一个事实,即您要遍历相同的元素多次,以计算子树的深度,然后计算其右子树和左子树的深度

当你有这样的重叠问题,这些问题可以由较小的问题推断出来时,你的脑海中一定会响起一声钟声:动态规划。您可以计算一个包含每个对应节点深度的
二进制树节点
(此树的形状与原始树相同)。然后,您只需遍历此树一次即可执行计算,总时间复杂度为
O(n)
(但使用的内存为
O(n)

public二进制树节点computeDepthTree(二进制树节点bt){
返回计算深度(bt,0);
}
公共二进制树节点computeDepthTree(二进制树节点bt,int深度){
BinaryTreeNode结果=新的BinaryTreeNode(深度);
if(bt.getLeftNode()!=null)
setLeftNode(computeDepthTree(bt.getLeftNode(),depth+1));
if(bt.getRightNode()!=null)
setRightNode(computeDepthTree(bt.getRightNode(),depth+1));
返回结果;
}

通过计算此树,当遍历给定节点时,您将在
O(1)
中访问其深度,因此比较同一父节点的子节点之间的深度将非常便宜

我重新格式化了代码以使其更具可读性,但您可以使用条件运算符对其进行改进(我没有这样做,因为我不想使代码变性)。很抱歉,它不太可读,感谢您的编辑。这就是为什么它是一条注释而不是答案。我已经确定了这个代码的效率的原因,并试图向您提出一个解决方案。如果我听起来完全没有经验,我很抱歉,但我不确定我将如何做到这一点。还有,你是说O(1)时间复杂度吗?不,这是一个
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;
}