一、是什么

在百度百科中,二叉树是这样定义的:
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。

二、例题

接下来我们来讲讲几种遍历的递归与迭代实现。

1、二叉树的前序遍历

给定一个二叉树,返回它的 前序 遍历。
示例: :::info 输入: [1,null,2,3]
1
\
2
/
3
输出: [1,2,3] ::: 进阶: 递归算法很简单,你可以通过迭代算法完成吗?

思路

递归算法就不多说了,很简单。

  1. var preorderTraversal = function(root) {
  2. const res = []
  3. const preOrder = function (root) {
  4. if (!root) return;
  5. res.push(root.val)
  6. preOrder(root.left)
  7. preOrder(root.right)
  8. }
  9. preOrder(root)
  10. return res
  11. };

当我们采用迭代时,我们可以通过用栈去模拟递归。
由于栈是先入后出的,所以在前序遍历中按照右左中的顺序入栈,这样在取得栈顶元素的过程中,才能按照中左右的顺序去操作。

  1. var preorderTraversal = function(root) {
  2. const res = []
  3. if (!root) return res
  4. const stack = [root]
  5. while (stack.length) {
  6. const node = stack.pop()
  7. res.push(node.val)
  8. node.right && stack.push(node.right)
  9. node.left && stack.push(node.left)
  10. }
  11. return res
  12. };

2.二叉树的中序遍历

给定一个二叉树,返回它的 中序 遍历。 :::info 输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2] :::

思路

具体就不细说了,与前序遍历相似,只是存入根节点的位置发生了改变,顺序为左根右

  • 递归算法

    1. var inorderTraversal = function(root) {
    2. const res = []
    3. const inorder = function(root) {
    4. if (!root) return;
    5. inorder(root.left)
    6. res.push(root.val)
    7. inorder(root.right)
    8. }
    9. inorder(root)
    10. return res
    11. };
  • 迭代算法

    1. var inorderTraversal = function(root) {
    2. const res = []
    3. if (!root) return res
    4. const stack = [root]
    5. while (stack.length) {
    6. const node = stack.pop()
    7. if (!node) {
    8. res.push(stack.pop().val)
    9. continue
    10. }
    11. // 存入栈顺序为: 右中左
    12. node.right && stack.push(node.right)
    13. stack.push(node)
    14. stack.push(null)
    15. node.left && stack.push(node.left)
    16. }
    17. return res
    18. };

    3.二叉树的后序遍历

    给定一个二叉树,返回它的 后序 遍历。 :::info 输入: [1,null,2,3]
    1
    \
    2
    /
    3
    输出: [3,2,1] :::

    思路

    具体就不细说了,与前序遍历相似,只是存入根节点的位置发生了改变,顺序为左右根

  • 递归

    1. var postorderTraversal = function(root) {
    2. const res = []
    3. const postorder = function(root) {
    4. if (!root) return;
    5. postorder(root.left)
    6. postorder(root.right)
    7. res.push(root.val)
    8. }
    9. postorder(root)
    10. return res
    11. };
  • 迭代

    1. var postorderTraversal = function(root) {
    2. const res = []
    3. if (!root) return res
    4. const stack = [root]
    5. while (stack.length) {
    6. const node = stack.pop()
    7. if (!node) {
    8. res.push(stack.pop().val)
    9. continue
    10. }
    11. stack.push(node)
    12. stack.push(null)
    13. node.right && stack.push(node.right)
    14. node.left && stack.push(node.left)
    15. }
    16. return res
    17. };

    4.二叉树的层序遍历

    给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 ```javascript 二叉树:[3,9,20,null,null,15,7],

    3 / \ 9 20 / \ 15 7

返回其层次遍历结果:

[ [3], [9,20], [15,7] ]

  1. <a name="Tf83y"></a>
  2. #### 思路
  3. 层序遍历是一道经典题,我们可以通过`DFS`或者`BFS`来解决。
  4. - **DFS(深度优先搜索遍历)**
  5. 遍历的时候记录里一下`level`,每次递归都把`level`+1,即可获得正确的层级,`push`到对应的数组即可
  6. ```javascript
  7. var levelOrder = function(root) {
  8. const res = []
  9. const dfs = function (root, level) {
  10. if (!root) return;
  11. // 创建当前层次的数组
  12. if (!res[level]) {
  13. res[level] = []
  14. }
  15. // 存入当前层次节点
  16. res[level].push(root.val)
  17. // 递归,层次加一
  18. dfs(root.left, level+1)
  19. dfs(root.right, level+1)
  20. }
  21. dfs(root, 0)
  22. return res
  23. };
  • BFS(广度优先搜索遍历)

利用队列先进先出的特性,在遍历到当前节点时,while 中对于每轮的节点开一个 for 循环加入到数组的一层中,将其子节点存入到队列中。

  1. var levelOrder = function(root) {
  2. const res = []
  3. if (!root) return res
  4. const queue = [root]
  5. while (queue.length) {
  6. const len = queue.length
  7. const level = []
  8. // 遍历当前层次节点
  9. for (let i = 0; i < len; i++) {
  10. const node = queue.shift()
  11. level.push(node.val)
  12. // 将当前节点的子节点存入队列
  13. node.left && queue.push(node.left)
  14. node.right && queue.push(node.right)
  15. }
  16. res.push(level)
  17. }
  18. return res
  19. };