引入
在面试中,二叉树的遍历是一个常见的题目。通常面试官会要求候选人解释并实现不同类型的遍历算法。这里我们将讨论四种主要的二叉树遍历方法:先序遍历(Pre-order)、中序遍历(In-order)、后序遍历(Post-order)和层序遍历(Level-order)。这些遍历方式的主要区别在于访问节点的顺序。
什么是二叉树?
二叉树是一种每个节点最多有两个子节点的数据结构,通常分为左子节点和右子节点。它由以下基本元素组成:
- 根节点(Root) :树的最顶端节点。
- 节点(Node) :树的基本组成部分,包含数据和指向左右子节点的引用。
- 叶子节点(Leaf Node) :没有子节点的终端节点。
如何生成树呢?
很简单,有树根,有左右孩子就行了。
function preOrder(root) {
// 退出条件
// 空树
if(root==null)
return
// 递归式
console.log(root.val);
preOrder(root.left)
preOrder(root.right)
}
const root={
val: 'A',
left:{
val:'B',
left:{
val:'D'
},
right:{
val:'E'
}
},
right:{
val:'C',
left:{
val:'F'
},
right:{
val:'G'
}
}
}
preOrder(root)
遍历二叉树
树的概念就是用递归的概念来定义的
- 它可以没用根节点,作为一个一棵空树
- 如果不是空树,那么必须由根节点,左子树和右子树组成,左右子节点分别是一棵二叉树。 所以我们使用递归的思想去遍历二叉树,就是最优解。
先序遍历(Pre-order)
退出条件为root===null,递归公式自顶向下,然后访问顺序,先序遍历首先访问根节点,然后递归地进行左子树的先序遍历,最后递归地进行右子树的先序遍历。其访问顺序为:根 -> 左 -> 右。
function preOrder(root) {
if (root === null) return;
console.log(root.val); // 访问当前节点
preOrder(root.left); // 遍历左子树
preOrder(root.right); // 遍历右子树
}
中序遍历(In-order)
中序遍历首先递归地进行左子树的中序遍历,然后访问根节点,最后递归地进行右子树的中序遍历。其访问顺序为:左 -> 根 -> 右。
function inOrder(root) {
if (root === null) return;
inOrder(root.left); // 遍历左子树
console.log(root.val); // 访问当前节点
inOrder(root.right); // 遍历右子树
}
后序遍历(Post-order)
后序遍历首先递归地进行左子树的后序遍历,然后递归地进行右子树的后序遍历,最后访问根节点。其访问顺序为:左 -> 右 -> 根。
function postOrder(root) {
if (root === null) return;
postOrder(root.left); // 遍历左子树
postOrder(root.right); // 遍历右子树
console.log(root.val); // 访问当前节点
}
层序遍历(Level-order)
层序遍历也被称为广度优先搜索(BFS),它按照树的层级从上到下逐层访问所有节点。同一层的节点按照从左到右的顺序访问。此遍历不需要使用递归,而是利用队列来实现。
class TreeNode{
constructor(val){
this.val=val;
this.left=null;
this.right=null;
}
}
const root=new TreeNode(1)
root.left=new TreeNode(2)
root.right=new TreeNode(3)
root.left.left=new TreeNode(4)
root.left.right=new TreeNode(5)
root.right.left=new TreeNode(6)
function levelOrderTraversal(root) {
if (root === null) return [];
const result = [];
const queue = [root];
while (queue.length > 0) {
const currentNode = queue.shift();
result.push(currentNode.val);
if (currentNode.left !== null) queue.push(currentNode.left);
if (currentNode.right !== null) queue.push(currentNode.right);
}
return result;
}
console.log(levelOrderTraversal(root))
总结:
当我们拿到题时,应该先把每一步骤想好,特别是用递归思想的题目,首先是退出条件是什么?其次递归公式是什么? 当想清楚这些,那么下笔如有神。