「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
关于二叉树的基本概念和入门教程,可以看我这篇文章 送给前端开发者的二叉树入门教程
今天主要给大家讲的是二叉树的前序遍历、中序遍历、和后序遍历。
例子
先看个例子: 我们拿到一颗二叉树,先说说三种遍历的结果
前序遍历:A B D E C F G
中序遍历:D B E A F C G
后序遍历:D E B F G C A
概念
然后来解释为什么是这样子的结果, 先看一下这三个遍历的定义:
前序遍历: 先访问根结点,然后遍历左子树,最后遍历右子树。
中序遍历: 先遍历左子树,然后访问根结点,最后遍历右子树。
后序遍历: 先遍历左子树,然后遍历右子树,最后访问根结点。
接着, 我们从一个最简单的例子入手分析
这个图中三种遍历的结果,结合我们刚刚的概念进行分析
前序遍历:A
B C
中序遍历:B A
C
后序遍历:B C A
简单理解, A
是我们的根节点, 前序遍历就是A
出现在最前面, 中序遍历就是A
出现在中间, 后序遍历就是A
出现在最后面。
到这一步,如果看懂了,那么接下来理解递归就完事了。如果没看懂,建议重头开始重新看一遍。
递归
当B
节点出现了子节点的时候, 三种遍历有什么不同呢?
前序遍历
首先来看前序遍历,前序遍历本来的顺序是 A B C
, 如果B
有子节点了,那么意味着我们要把数据拆开
拆成 A => ( B子树 ) => C
。
然后我们来构造B子树的, 又回到上面那一步了
这个结构就会了吧, 前序结果是 B D E
加上刚才上一步的A C, 所以结果是 A B D E C
。
中序遍历
其次来看中序遍历,中序遍历本来的顺序是 B A C
, 如果B
有子节点了,那么意味着我们要把数据拆开
拆成 ( B子树 ) => A => C
。
B子树的中序结果是 D B E
加上刚才上一步的A C, 所以结果是 D B E A C
。
后序遍历
最后来看后序遍历,后序遍历本来的顺序是 B C A
, 如果B
有子节点了,那么意味着我们要把数据拆开
拆成 ( B子树 ) => C => A
。
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;
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。