迭代打印完整的二叉树

时间:2015-11-23 00:22:02

标签: c# .net binary-tree

已解决的问题:如果没有任何意义,请确保您的代码与您认为的一样孤立。延迟不在常规本身,而是将结果复制到文本框中。不确定那里发生了什么,但至少现在它是有道理的。抱歉浪费了人们的时间!因为我在这个领域非常弱,但是我仍然希望看到这个的迭代实现,所以我现在暂时打开这个问题。

我有一个完整的二进制树形式:

root
 /\
1  node
    /\
   2  3

我想要做的是将其打印为“(1,(2,3))”,但是使用迭代算法,因为我使用的递归算法已经莫名其妙地减慢了十倍到几百倍虽然代码或树的相关部分绝对没有变化,但树木较大。 (这显然是递归本身就是问题所在,所以我认为它与堆栈问题有关,尽管我在这个问题上也很老实。)

我整个下午一直在使用传统迭代树行走逻辑的变体来探索逻辑,而我却无法让它工作。任何人都能指出我在正确的方向吗?我在C#工作,但我真的只需要一个算法,所以任何.NET语言的例子都应该这样做。

更新:原始的递归代码就是这样。 IsBaseGem是一个自动实现的bool,ID是一个自动实现的字符串。

private string DoFullCombine() => this.Component1.DoSubCombine() + "+" + this.Component2.DoSubCombine();
private string DoSubCombine() => this.IsBaseGem ? this.ID : "(" + this.DoFullCombine() + ")";

当前的迭代代码,此时非常明显地被破坏,因为它永远不会终止:

public string GetFullCombine()
{
    var sb = new StringBuilder();
    var gemStack = new Stack<Gem>();
    Gem gem = this;
    while (gem != null)
    {
        while (!gem.IsBaseGem)
        {
            sb.Append('(');
            gemStack.Push(gem);
            gem = gem.Component1;
        }

        sb.Append(gem.ID);
        sb.Append('+');
        gem = gemStack.Pop().Component2;
        if (gem.IsBaseGem)
        {
                sb.Append(gem.ID);
                sb.Append(')');
                gem = gemStack.Pop();
            }
        }

        return sb.ToString();
}

1 个答案:

答案 0 :(得分:0)

我不明白为什么递归算法应该慢得多。编辑现在显然问题出在其他地方,但我会把它作为参考。

private void DoFullCombine(StringBuilder sb)
{
    this.Component1.DoSubCombine(sb);
    sb.Append("+");
    this.Component2.DoSubCombine(sb);
}
private void DoSubCombine(StringBuilder sb)
{
    if (this.IsBaseGem)
    {
        sb.Append(this.ID);
    }
    else
    {
        sb.Append("(");
        this.DoFullCombine(sb);
        sb.Append(")");
    };
}

修改

我做了非递归版本。它与递归变体的速度大致相同。最棘手的是括号,我在堆栈上按空以标记它们应该在哪里。

   public string GetFullCombineNonRecur()
    {
        var sb = new StringBuilder();
        var gemStack = new Stack<Gem>();
        Gem gem = this;
        int level = 0;
        while (true)
        {
            while (!gem.IsBaseGem)
            {
                sb.Append('('); level++;
                gemStack.Push(gem);
                gem = gem.Component1;
            }

            sb.Append(gem.ID);

            do
            {
                if (level == 0)
                {
                    if (gem != this) { sb.Remove(0, 1).Remove(sb.Length - 1, 1); }
                    return sb.ToString();
                }
                gem = gemStack.Pop();
                if (gem == null) // is ")" mark
                {
                    sb.Append(')'); level--;
                }
            } while (gem == null);

            sb.Append('+');
            gemStack.Push(null); // push ")" mark here
            gem = gem.Component2;
        }
    }