二叉树及其遍历方式详解

48 阅读3分钟

二叉树及其遍历方式详解

在数据结构中,树是一种重要的非线性结构,而二叉树作为树的一种特殊形式,因其结构清晰、操作便捷而被广泛应用。本文将结合具体代码,详细介绍二叉树的基本概念及常见遍历方式。

二叉树的基本概念

二叉树是一种递归定义的数据结构,它具有以下特点:

  • 可以是空树(没有任何节点)
  • 若非空,则由根节点、左子树和右子树组成,且左右子树也都是二叉树
  • 左右子树有严格的顺序,不能随意交换

二叉树的核心概念还包括:

  • 层次:根节点位于第一层,其子女位于第二层,以此类推
  • 高度:从叶子节点开始计算,逐层向上累加
  • :一个节点拥有的子树数量
  • 叶子节点:度为 0 的节点(没有子节点)

二叉树的节点定义

在 JavaScript 中,我们通常使用构造函数来定义二叉树的节点:

class TreeNode {
    constructor(val) {
        this.val = val;  // 节点的值
        this.left = this.right = null;  // 左右子节点的引用,初始为null
    }
}

使用该构造函数,我们可以创建一个二叉树实例:

// 创建节点
const root = new TreeNode(1);
const node2 = new TreeNode(2);
const node3 = new TreeNode(3);
// 构建树结构
root.left = node2;
root.right = node3;

也可以使用对象字面量的方式直接表示二叉树:

let tree = {
    val: 1,
    left: {
        val: 2,
        left: { val: 4, left: null, right: null },
        right: { val: 5, left: null, right: null }
    },
    right: { val: 3, left: null, right: null }
};

二叉树的遍历方式

遍历是二叉树最基本的操作,指按某种顺序访问树中的所有节点,且每个节点仅被访问一次。常见的二叉树遍历方式有四种:前序遍历、中序遍历、后序遍历和层序遍历。

1. 前序遍历

前序遍历的顺序是:根节点 → 左子树 → 右子树。采用递归实现非常简洁:

function preorder(root) {
    if (!root) {
        return;
    }
    console.log(root.val);  // 先访问根节点
    preorder(root.left);    // 再遍历左子树
    preorder(root.right);   // 最后遍历右子树
}

2. 中序遍历

中序遍历的顺序是:左子树 → 根节点 → 右子树:

function inorder(root) {
    if (!root) {
        return;
    }
    inorder(root.left);     // 先遍历左子树
    console.log(root.val);  // 再访问根节点
    inorder(root.right);    // 最后遍历右子树
}

3. 后序遍历

后序遍历的顺序是:左子树 → 右子树 → 根节点:

function postorder(root) {
    if (!root) {
        return;
    }
    postorder(root.left);   // 先遍历左子树
    postorder(root.right);  // 再遍历右子树
    console.log(root.val);  // 最后访问根节点
}

4. 层序遍历

层序遍历(也叫广度优先遍历)与上述三种深度优先遍历不同,它是按照树的层次从上到下、每层从左到右的顺序访问节点。实现层序遍历通常需要借助队列:

function levelOrder(root) {
    if (!root) return [];  // 空树返回空数组
    const result = [];
    const queue = [root];  // 初始化队列,将根节点入队
    
    while (queue.length) {  // 队列不为空时循环
        const node = queue.shift();  // 出队一个节点(FIFO原则)
        result.push(node.val);       // 访问节点值
        
        // 将左右子节点入队(如果存在)
        if (node.left) {
            queue.push(node.left);
        }
        if (node.right) {
            queue.push(node.right);
        }
    }
    return result;
}

总结

二叉树的遍历是处理树结构问题的基础,四种遍历方式各有特点:

  • 前序、中序、后序遍历基于递归实现,本质上是深度优先搜索
  • 层序遍历基于队列实现,本质上是广度优先搜索