题目:二叉树的中序遍历

给定一个二叉树,返回它的中序遍历。

示例:
输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]
  • 进阶: 递归算法很简单,你可以通过迭代算法完成吗?

来源:力扣(LeetCode)第94题

链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal

分析:

两种方法,一种是最常用的递归遍历,非常简单。第二种是迭代遍历,需要用到栈。本文章分析第二种算法。

思路:

维护一个栈,每次经过一个节点,就入栈,当节点的左节点没有值时出栈,并继续从出栈的那个节点找它的右节点。

  1. 维护一个栈stack和要储存答案的列表ans
  2. 写一个循环,不停地将左节点一层一层的入栈
  3. 当左节点为None时,不要入栈,并且将栈顶节点弹出
  4. 拿到栈顶节点的value,并且进入该节点的右节点(因为中序遍历是左,中,右)
  5. 继续拿这个节点的左节点,重复2-4步
  6. 当节点值为None 或者 stack为空时结束循环

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        stack = []
        ans = []
        tail = root
        while tail is not None or stack:
            while tail is not None:
                stack.append(tail)
                tail = tail.left
            tail = stack.pop()
            ans.append(tail.val)
            tail = tail.right
        return ans

顺便把递归遍历的代码一起放上来

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if root is None:
            return []
        stack = []
        self.recursion(stack, root)
        return stack
        
    def recursion(self, stack: List[int], root: TreeNode) -> None:
        if root.left != None:
            self.recursion(stack, root.left)
        stack.append(root.val)
        if root.right != None:
            self.recursion(stack, root.right)

复杂度分析:

  • 递归法
    • 时间复杂度: O(n) (递归函数 T(n)=2⋅T(n/2) + 1)
    • 空间复杂度: O(logn)
  • 迭代法
    • 时间复杂度: O(n)
    • 空间复杂度: O(n)

总体来说,迭代法比递归法速度更快,毕竟递归调用很耗时,而递归法节省的空间更多,适合资源不多时使用。

LeetCode上还有一种方法叫做莫里斯遍历,复杂度与迭代法一样,没仔细看过。在这里放上链接 > https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode/

总结:

中序遍历的两种方法各有各的优点,尤其是迭代法,时间用的更少,就是实现上没有递归法那么方便。要注意通过栈来储存每次进过的节点,不然的话你再想找之前的节点就找不到了。。