[路飞]_一文彻底搞懂二叉树的前序、中序、后序遍历

·  阅读 96
[路飞]_一文彻底搞懂二叉树的前序、中序、后序遍历

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

关于二叉树的基本概念和入门教程,可以看我这篇文章 送给前端开发者的二叉树入门教程

今天主要给大家讲的是二叉树的前序遍历、中序遍历、和后序遍历。

例子

src=http___img.xiaobotalk.cn_blog_biTree01.png&refer=http___img.xiaobotalk.jfif

先看个例子: 我们拿到一颗二叉树,先说说三种遍历的结果

前序遍历:A B D E C F G

中序遍历:D B E A F C G

后序遍历:D E B F G C A

概念

然后来解释为什么是这样子的结果, 先看一下这三个遍历的定义:

前序遍历: 先访问根结点,然后遍历左子树,最后遍历右子树。

中序遍历: 先遍历左子树,然后访问根结点,最后遍历右子树。

后序遍历: 先遍历左子树,然后遍历右子树,最后访问根结点。

接着, 我们从一个最简单的例子入手分析

snipaste_20211124_095721.png

这个图中三种遍历的结果,结合我们刚刚的概念进行分析

前序遍历:A B C

中序遍历:B A C

后序遍历:B C A

简单理解, A 是我们的根节点, 前序遍历就是A出现在最前面, 中序遍历就是A出现在中间, 后序遍历就是A出现在最后面。

到这一步,如果看懂了,那么接下来理解递归就完事了。如果没看懂,建议重头开始重新看一遍。

递归

snipaste_20211124_100314.png

B节点出现了子节点的时候, 三种遍历有什么不同呢?

前序遍历

首先来看前序遍历,前序遍历本来的顺序是 A B C, 如果B有子节点了,那么意味着我们要把数据拆开 拆成 A => ( B子树 ) => C

然后我们来构造B子树的, 又回到上面那一步了

snipaste_20211124_100830.png

这个结构就会了吧, 前序结果是 B D E

加上刚才上一步的A C, 所以结果是 A B D E C

中序遍历

其次来看中序遍历,中序遍历本来的顺序是 B A C, 如果B有子节点了,那么意味着我们要把数据拆开 拆成 ( B子树 ) => A => C

snipaste_20211124_100830.png

B子树的中序结果是 D B E

加上刚才上一步的A C, 所以结果是 D B E A C

后序遍历

最后来看后序遍历,后序遍历本来的顺序是 B C A , 如果B有子节点了,那么意味着我们要把数据拆开 拆成 ( B子树 ) => C => A

snipaste_20211124_100830.png

B子树的后序结果是 D E B

加上刚才上一步的A C, 所以结果是 D E B C A

理解了到这一步, 回过头去看题目中的三个遍历结果,没看懂的话欢迎评论区diss我哈哈,我继续改进。

实现

前序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
function postorderTraversal(root) {
    return root ? getNextNode(root) : [];
};


function getNextNode(node, result = []) {
    result.push(node.val); // 前序遍历,把push当前节点放在前面
    node.left && getNextNode(node.left, result);
    node.right && getNextNode(node.right, result);
    return result;
};
复制代码

中序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
function postorderTraversal(root) {
    return root ? getNextNode(root) : [];
};


function getNextNode(node, result = []) {
    node.left && getNextNode(node.left, result);
    result.push(node.val); // 中序遍历,把push当前节点放在中间
    node.right && getNextNode(node.right, result);
    return result;
};
复制代码

后序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
function postorderTraversal(root) {
    return root ? getNextNode(root) : [];
};


function getNextNode(node, result = []) {
    node.left && getNextNode(node.left, result);
    node.right && getNextNode(node.right, result);
    result.push(node.val); // 后序遍历,把push当前节点放在最后面
    return result;
};
复制代码

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。

分类:
前端
标签: