【问题标题】:Constructing a Binary Tree from its traversals从遍历构造二叉树
【发布时间】:2011-11-15 08:39:49
【问题描述】:

考虑到它的遍历,我正在尝试构建一棵二叉树(不平衡)。我目前正在做预购+订购,但是当我发现后订购根本没有问题。

我意识到已经有一些关于这个话题的问题,但他们似乎都没有回答我的问题。我有一个递归方法,它采用二叉树的 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
}

基本上,我构建了额外的数组来容纳左右子树的前序遍历和中序遍历(这似乎非常低效,但我想不出没有辅助方法的更好方法)。

任何想法都将不胜感激。

旁注:在调试时,根注释似乎从未接收到与其他节点的连接(它们保持为空)。不过据我所知,这不应该发生......

编辑:澄清一下,该方法在第 21 行抛出 IllegalArgumentException(for 循环的else 分支,在遍历包含不同元素时抛出。 p>

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

【问题讨论】:

    标签: java binary-tree


    【解决方案1】:

    这段代码对我来说很可疑

    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. 你抛出异常

    无论哪种方式,您都不会真正增加 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] 以清楚起见)。而且,我绝不肯定它是完全正确的。不过,它可能更接近你想要的

    【讨论】:

    • 哦。那是一个愚蠢的错误。不幸的是,它仍然没有将根链接到任何节点,但至少现在我有一个前进的方向。谢谢。
    • 谢谢,我想通了。我的循环条件没有丢失“小于或等于”,而不仅仅是“小于”。谢谢你的推动。
    猜你喜欢
    • 1970-01-01
    • 2014-12-30
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    相关资源
    最近更新 更多