94.二叉树的中序遍历
给定一个二叉树的根节点 root ,返回它的 中序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
- 树中节点数目在范围
[0, 100]内 -100 <= Node.val <= 100解题思路:
方法1:递归
按照左子树——根节点——右子树的顺序访问这棵树,
在访问左子树或者右子树的时候按照同样的方式遍历,
直到遍历完整棵树。
var inorderTraversal = function(root) {
let res=[];
inorder(res,root);
return res;
};
function inorder(res,root){
if(root){
inorder(res,root.left);
res.push(root.val);
inorder(res,root.right);
}
}
方法2:迭代,使用栈维护左子树
1.根节点入栈->2.左子树入栈->3.弾栈,访问节点->
- 4.1 有右子树,将右子节点视为根节点,重复步骤1、2、3、4
- 4.2 无右子树,重复步骤3、4
var inorderTraversal = function(root) {
let stack=[],result=[];
while(root || stack.length){
while(root){
stack.push(root);
root=root.left;
}
root=stack.pop();
result.push(root.val);
root=root.right;
}
return result;
};
方法3:使用指针指示根节点的中序遍历前驱节点
假设当前遍历到的节点为 root,
- 如果 root 无左孩子,先将root.val的值加入result数组,再访问root的右子树
- 如果 root 有左孩子,则找到root左子树上最右的节点(即root 在中序遍历中的前驱节点)pre,
- 如果pre的右孩子为空,则将其右孩子指向root,即pre.right=root,然后访问root的左子树
- 如果pre的右孩子不为空,则此时有pre.right==root,说明已经访问完root的左子树,
此时将pre的右孩子置空,然后将root.val的值加入result数组,再访问root的右孩子,
重复上述操作,直至访问完整棵树。
var inorderTraversal = function(root) {
let res=[],pre=null;
while(root){
if(root.left){
pre=root.left;
while(pre.right && pre.right!==root){
pre=pre.right;
}
if(!pre.right){
pre.right=root;
root=root.left;
}else{
pre.right=null;
res.push(root.val);
root=root.right;
}
}else{
res.push(root.val);
root=root.right;
}
}
return res;
};