返回树的inorder字符串

时间:2011-02-22 10:59:25

标签: java recursion tree inorder

EDIT 这已通过使用此线程中建议的StringBuilder解决。谢谢:D

你好,

我有一棵树,我正在尝试按顺序返回内容的字符串。

我现在可以用这样的东西打印出树:

    public void inOrder() {
        if (left != null) left.inOrder();
        System.out.print(content + " ");
        if (right != null) right.inOrder();
    }

但我想要做的是返回String(而不是在递归时打印出每个节点内容),我无法弄清楚如何做到这一点。我尝试了下面代码的许多变体,但它只返回它在递归中找到的最后一个元素。

 public String inOrder(String string) {
        if (left != null) left.inOrder(string);
        string += content;
        if (right != null) right.inOrder(string);

        return string;
    }

4 个答案:

答案 0 :(得分:5)

字符串在java中是不可变的。您没有将新String连接到旧String,您正在创建新String并使string变量指向它。结果是您在不同的时间点有许多不相关的字符串和string变量指向它们。

您需要将可变对象传递给您的函数,例如StringBuilder。此解决方案具有额外的优势,因为它可以避免不必要的对象分配,因此效率更高。

答案 1 :(得分:3)

如果你想用字符串连接做这个,你的第二个例子几乎可以工作 - 问题只在于你丢弃了递归调用的结果。

/**
 * creates an Inorder-string-view of this tree and appends it to the given string.
 * @return the new String.
 */
public String inOrder(String string) {
    if (left != null)
        string = left.inOrder(string);
    string += content;
    if (right != null)
        string = right.inOrder(string);
    return string;
}

但这是(对于较大的树)可怕的低效率,因为每个+=实际上创建一个新的String,复制stringcontent的字符 - 因此每个内容字符串都在事实复制the number of later nodes(按顺序)次数(+1)。一个更好的方法是:

public String inOrder() {
    String leftS; String rightS;
    if (left != null)
       leftS = left.inOrder();
    else
       leftS = "";
    if (right != null)
       rightS = right.inOrder();
    else
       rightS = "";
    return leftS + content + rightS;
}

或者更短一些:

public String inOrder {
   return
      (left != null ? left.inOrder() : "") +
      content +
      (right != null ? right.inOrder() : "");
}

现在每个内容字符串仅复制上面的节点数次(+1),这对于“通常”(非极不平衡)树来说要小得多。 (这种变体也很容易并行化。)

但事实上,StringBuilder版本通常是首选版本,因为它只复制每个内容字符串一次(当它附加到StringBuilder时),并且在内部调整大小时可能会多一些StringBuilder(如果你可以在实际转换之前估计最终大小,那么创建一个足够大的StringBuilder)。

答案 2 :(得分:2)

字符串在Java中是不可变的,当您向String添加内容时,会创建一个新对象。因此,在方法范围之外,这种变化是不可见的。

尝试使用StringBuilder而不是String:

public StringBuilder inOrder(StringBuilder string) {
        if (left != null) left.inOrder(string);
        string.append(content);
        if (right != null) right.inOrder(string);

        return string;
}

您可以在这里阅读:http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html以了解Java传递方法参数的方式以及为什么Strings immutability是原始代码中的问题。

此致 索林。

答案 3 :(得分:0)

Java是按值传递的。此方法无法更改对传递给方法的对象的引用。您可以更改对象的内容,但不能使用字符串,因为它们是不可变的(它们的内容不能更改)。

该行

string += content;

将新的String对象影响到字符串变量。它不会更改原始String对象的内容。

您需要将StringBuilder实例传递给您的方法,并附加到此StringBuilder:

public String inOrder() {
    StringBuilder strinBuilder = new StringBuilder();
    postOrder(stringBuilder);
    return stringBuilder.toString();
}

private void postOrder(StringBuilder stringBuilder) {
    if (left != null) left.postOrder(stringBuilder);
    if (right != null) right.postOrder(stringBuilder);
}