【二叉树】非递归遍历方法

1.事情起因

刷力扣到了二叉树遍历算法部分,递归方法实在太简单了,对应三种前中后序为:

  • 前:根左右
  • 中:左根右
  • 后:左右根

但是发现时间复杂度很高,递归开辟隐式栈空间导致的,所以研究了下使用“迭代”方法,自己显示开辟一个栈空间来实现,结果不错,很大程度提高了计算速度。我是一名Unity程序,所以使用C#。

2.二叉树遍历通过迭代实现

三种前中后序迭代实现方式思路均略有不同,所以在此记录下来。

2.1 前序遍历(迭代法)

思路(根左右):

  • 开辟一个辅助栈空间,根入栈,顶出栈进行操作输出,右左入栈(为什么?因为右左入,左右出,符合前序的顺序)。以此遍历直到空栈结束。
public IList PreorderTraversal(TreeNode root)
{
    IList t = new List();
    if (root == null)
        return t;
    Stack s = new Stack();
    s.Push(root);
    while (s.Count > 0)
    {
        TreeNode n = s.Pop();
        t.Add(n.val);
        if (n.right != null)
            s.Push(n.right);
        if (n.left != null)
            s.Push(n.left);
    }
    return t;
}

2.2 中序遍历(迭代法)

思路(左根右):

  • 中序遍历并非简单调整代码顺序就能实现,因为遍历顺序与操作输出的顺序不一致,所以需采用自顶向下找最左叶子结点,然后向上,之后再出栈处理右节点。
public IList PrecenterTraversal(TreeNode root)
{
    IList t = new List();
    if (root == null)
        return t;
    Stack s = new Stack();
    s.Push(root);
    TreeNode r = root;
    while (r != null && s.Count > 0)
    {
        if (r != null)
        {
            s.Push(r);
            r = r.left;
        }
        else
        {
            r = s.Pop();
            t.Add(r.val);
            r = r.right;
        }
    }
    return t;
}

2.3 后序遍历(迭代法)

思路(左右根):

  • 后序遍历可以在前序遍历的基础之上变种,前序入栈操作顺序为根右左,调整为根左右,则输出顺序就是根右左,再对输出结果Reverse,就变成目标的左右根顺序了。
  • 重申一下:根右左、根左右(这是入栈顺序),对应出栈顺序为根左右、根右左(这是操作输出顺序),那么反转根右左,就变成了左右根。
public IList PostorderTraversal(TreeNode root)
{
    List t = new List();
    if (root == null)
        return t;
    Stack s = new Stack();
    s.Push(root);
    while (s.Count > 0)
    {
        TreeNode n = s.Pop();
        t.Add(n.val);
        if (n.left != null)
            s.Push(n.left);
        if (n.right != null)
            s.Push(n.right);
    }
    t.Reverse();
    return t;
}

3.优化结果

  • 从力扣提交记录上看,耗时排名上升幅度很大
    递归 迭代
    耗时排名 战胜14% 战胜98%

你可能感兴趣的:(【6.算法题】,深度优先遍历,数据结构)