874 字
4 分钟
算法之二叉树的3种遍历

一. 前序遍历(中左右)#

144.二叉树前序遍历

image-20210614161741801

1. 递归实现#

按照中间节点先遍历,在遍历左右节点

/**
* 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[]}
*/
var preorderTraversal = function (root) {
let number = [];
getNode(root, number);
return number;
};
const getNode = (node, number) => {
if (node) {
number.push(node.val);
if (node.left) {
getNode(node.left, number)
}
if (node.right) {
getNode(node.right, number);
}
}
}

2. 迭代实现#

以显示栈的方式模仿递归。

  • 初始化栈,并将根节点入栈;
  • 当栈不为空时:
    • 弹出栈顶元素 n,并将值添加到结果中
    • 如果 n 的右节点存在,入栈
    • 如果 n 的左节点存在,入栈
/**
* 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[]}
*/
var preorderTraversal = function (root) {
let number = [];
let stack = [root];
while (stack.length) {
const current = stack.shift();
if(current){
number.push(current.val);
if(current.right){
stack.unshift(current.right)
}
if(current.left){
stack.unshift(current.left);
}
}
}
return number;
};

二. 中序遍历(左中右)#

1. 递归实现#

先左节点,然后中间节点,之后右节点

/**
* 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[]}
*/
var inorderTraversal = function (root) {
const number = [];
getNode(root, number);
return number
};
const getNode = (node, number) => {
if (node && node.left) {
getNode(node.left, number)
}
node && number.push(node.val);
if (node && node.right) {
getNode(node.right, number)
}
}

2. 迭代实现#

原理:

image-20210614165726412

image-20210614165746953

image-20210614165812531

代码一:

const inorderTraversal = (root) => {
const res = [];
const stack = [];
while (root) { // 能压入栈的左子节点都压进来
stack.push(root);
root = root.left;
}
while (stack.length) {
let node = stack.pop(); // 栈顶的节点出栈
res.push(node.val); // 在压入右子树之前,处理它的数值部分(因为中序遍历)
node = node.right; // 获取它的右子树
while (node) { // 右子树存在,执行while循环
stack.push(node); // 压入当前root
node = node.left; // 不断压入左子节点
}
}
return res;
};

代码二:

/**
* 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[]}
*/
var inorderTraversal = function (root) {
const number = [];
let stack = [];
let tempNode = root;
while(tempNode || stack.length){
if(tempNode){
stack.unshift(tempNode);
tempNode = tempNode.left;
}else{
tempNode = stack.shift();
number.push(tempNode.val);
tempNode = tempNode.right
}
}
return number;
};

三. 后序遍历#

1. 递归方式#

左右中

/**
* 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[]}
*/
var postorderTraversal = function(root) {
let number = [];
getNode(root,number);
return number;
};
const getNode = (node, number)=>{
if(node && node.left){
getNode(node.left, number);
}
if(node && node.right){
getNode(node.right, number)
}
node && number.push(node.val);
}

2. 迭代方式#

先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:

image-20210614173144699

/**
* 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[]}
*/
const postorderTraversal = (root) => {
const res = [];
const stack = [root];
while(stack.length > 0) {
const node = stack.pop()
node && res.unshift(node.val)
if(node?.left) {
stack.push(node.left)
}
if(node?.right) {
stack.push(node.right)
}
}
return res
}
算法之二叉树的3种遍历
https://nollieleo.github.io/posts/算法之二叉树的3种遍历/
作者
翁先森
发布于
2021-06-14
许可协议
CC BY-NC-SA 4.0