从遍历构造二叉树

时间:2011-11-15 08:39:50

标签: java binary-tree

我正在尝试构造一个二叉树(不平衡),给定它的遍历。我目前正在预订+订购,但是当我想出这个问题后,订购后就没有问题了。

我意识到这个话题已经存在一些问题,但他们似乎都没有回答我的问题。我有一个递归方法,它采用二阶树的Preorder和Inorder来重构它,但由于某种原因无法将根节点与后续子节点链接起来。

注意:我不想要解决方案。我一直在试图弄清楚这几个小时,甚至在纸上记下了递归,一切看起来都很好......所以我必须错过一些微妙的东西。这是代码:

    public static <T> BinaryNode<T> prePlusIn( T[] pre, T[] in)
{
    if(pre.length != in.length)
        throw new IllegalArgumentException();

    BinaryNode<T> base = new BinaryNode();
    base.element = pre[0]; // * Get root from the preorder traversal.
    int indexOfRoot = -1 ;

    if(pre.length == 0 && in.length == 0)
        return null;

    if(pre.length == 1 && in.length == 1 && pre[0].equals(in[0]))
        return base; // * If both arrays are of size 1, element is a leaf.

    for(int i = 0; i < in.length -1; i++){
        if(in[i].equals(pre[0])){    // * Get the index of the root
            indexOfRoot = i; // in the inorder traversal.
            break;
        } 

    }   // * If we cannot, the tree cannot be constructed as the traversals differ.

        if (indexOfRoot == -1) throw new IllegalArgumentException();

    // * Now, we recursively set the left and right subtrees of 
    // the above "base" root node to whatever the new preorder
    // and inorder traversals end up constructing.

    T[] preleft = Arrays.copyOfRange(pre, 1, indexOfRoot + 1);
    T[] preright = Arrays.copyOfRange(pre, indexOfRoot + 1, pre.length);
    T[] inleft = Arrays.copyOfRange(in, 0, indexOfRoot);
    T[] inright = Arrays.copyOfRange(in, indexOfRoot + 1, in.length);

    base.left = prePlusIn( preleft, inleft); // * Construct left subtree.
    base.right = prePlusIn( preright, inright); // * Construc right subtree.

    return base; // * Return fully constructed tree
}

基本上,我构造了另外的数组,它们包含左右子树的预先和顺序遍历(这看起来非常低效,但我想不出更好的方法,没有帮助方法)。

任何想法都会非常感激。

旁注:在调试时,根音注释似乎永远不会收到与其他节点的连接(它们保持为空)。从我所看到的情况来看,这不应该发生......

编辑:为了澄清,该方法抛出了else循环的IllegalArgumentException @第21行(for分支,如果遍历包含不同,则应该抛出元件。

EDIT2 :感谢来自@Philip的有用帖子(巧合的是,我们有相同的名字......好玩!)。但是,如果有人提出任何提高效率的建议,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

这段代码对我非常怀疑

for(int i = 0; i < in.length -1; i++){
    if(in[i].equals(base.element)){    // * Get the index of the root
        indexOfRoot = i; // in the inorder traversal.
        break;
    } // * If we cannot, the tree cannot be constructed as the traversals differ.
    else throw new IllegalArgumentException();
}

您进入循环并且i设置为0,如果i小于in.length - 1,则评估循环体是if表达式。在这一点上,将发生两件事之一

  1. in[i]等于base.element,在这种情况下,indexOfRoot将设为0,您将摆脱循环
  2. 您抛出异常
  3. 无论哪种方式,你都不会实际增加i

    尝试重做这个循环来做你想要的,因为它肯定没有做你想要的。您可以尝试类似

    的内容
    int indexOfRoot = -1; //an impossible value
    for(int i = 0; i < in.length -1; i++){
        if(in[i].equals(base.element)){    // * Get the index of the root
            indexOfRoot = i; // in the inorder traversal.
            break;
        } 
    } 
    if(indexOfRoot == -1){//if the root was never set
        throw new IllegalArgumentException();
    }
    

    虽然这仍然有点难看(但有一点,base.element永远不会改变,所以你可能想要使用pre[0]来表示清晰度。并且,我绝不确定它是完全正确的。不过,它可能更接近你想要的东西