LeetCode 题解(5):二叉树-遍历
learn from cyc2018 and LeetCode
1 | // Definition for a binary tree node. |
二叉树的遍历方式有:
- 广度遍历:层次遍历
- 深度遍历:前序、中序、后序遍历
二叉树的层次遍历 (BFS)
二叉树的层次遍历可以借助队列来实现,由于队列是先进先出的,因此可以
- 先让根入队,在根出队的同时,让根的左孩子入队,再让根的右孩子入队,这样左孩子会首先被访问。
- 被访问之后,左孩子出队的同时打印左孩子,并让左孩子的孩子入队。
- 以此类推,直到队列为空。
1 | class Solution{ |
637. Average of Levels in Binary Tree (easy)
问题描述
求二叉树每层结点的平均值。
题解
利用两层循环,使得大循环中每次增加一整层元素,而非单个元素。
1 | class Solution { |
相关问题
102. Binary Tree Level Order Traversal (medium)
107. Binary Tree Level Order Traversal II (easy)
102. Binary Tree Level Order Traversal (medium)
问题描述
层次遍历二叉树,使得每层元素存在于一个向量中。
题解
1 | class Solution { |
相关问题
103. Binary Tree Zigzag Level Order Traversal (medium)
107. Binary Tree Level Order Traversal II (easy)
637. Average of Levels in Binary Tree (easy)
107. Binary Tree Level Order Traversal II (easy)
问题描述
与上题一样,但是结果先输出最底层,后输出顶层。
题解
增加一个 reverse 即可。
1 | class Solution { |
相关问题
102. Binary Tree Level Order Traversal (medium)
637. Average of Levels in Binary Tree (easy)
513. Find Bottom Left Tree Value (medium)
问题描述
寻找二叉树最底层最左边元素的值。
题解
与 102. Binary Tree Level Order Traversal (medium) 一样,输出结果中的最后一列首位即可。
1 | class Solution { |
二叉树的深度优先遍历 (DFS)
二叉树的深度优先遍历分为:前序遍历、中序遍历、后序遍历
其递归实现非常简单。
1 | // 前序遍历 |
而二叉树深度优先遍历的非递归形式需要用到栈,利用栈先进后出的特性,先将根节点入栈,栈不为空时 pop ,然后将右子树入栈,再将左子树入栈,下面将分别实现三种二叉树深度优先遍历的非递归形式。
144. Binary Tree Preorder Traversal (medium)
问题描述
实现二叉树前序遍历的非递归版本。
题解
1 | class Solution { |
94. Binary Tree Inorder Traversal (medium)
问题描述
二叉树中序遍历的非递归版本。
题解
参考 博客
对于中序遍历来说,先访问左子树、后根节点、再访问右子树,那么第一个被我们访问的元素,一定是最左边的元素:
1 | TreeNode* p = root; |
此时,有如下两种情形:

不管对于哪种情况,找到该元素之后,理所当然应该出栈,并访问该元素。
1 | p = s.top(); |
接下来,对于上图 a 中的情况:接下来我们只需要访问其根节点,那么继续执行:
1 | p = s.top(); |
左孩子和根都访问完后,接着只需要访问其右子树即可。
1 | p = p->right; |
这样就又会开始新一轮代码,继续执行下去。
而对于上图情况 b。由于没有左孩子,根节点就是中序序列中的第一个,然后就直接进入右子树,开始新一轮代码。
那么,两图的情况,我们可以统一处理为:
1 | p = s.top(); |
那么,我们最终的结果就为:
1 | class Solution { |
145. Binary Tree Postorder Traversal (hard)
问题描述
实现后序遍历的非递归版本。
题解
有一种简单的处理技巧:将前序遍历入栈顺序修改为 root, left, right 之后,只需要翻转最终结果即可。
1 | class Solution { |
显然,我们只是最终的结果和后序遍历的结果一致,但并没有真正意义上实现后序遍历。
参考 博客
后序遍历的难点在于需要判断上次访问的节点位于左子树,还是右子树。如果位于左子树,则需要跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。
1 | class Solution { |