二叉树入门全攻略:从树的概念到遍历实现

🏠个人主页:黎雁

🎬作者简介:C/C++/JAVA后端开发学习者

❄️个人专栏:C语言数据结构(C语言)EasyX游戏规划程序人生

✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

二叉树入门全攻略:从树的概念到遍历实现✨

你好!欢迎来到数据结构系列二叉树篇的第一篇内容~

在前面的栈与队列篇中,我们掌握了两种经典的线性结构变种,而今天要解锁的二叉树,是数据结构世界中第一个真正意义上的非线性结构。它打破了线性排列的限制,以分支+层级的形式组织数据,是后续学习平衡树、红黑树、B树等高级数据结构的基础,更是算法面试中的高频考点🌳

准备好了吗?让我们从树的基础概念入手,一步步吃透二叉树的核心知识!🚀


文章摘要

本文为数据结构系列二叉树篇首篇入门内容,系统讲解树与二叉树的核心概念、结构特征及关键术语,重点剖析二叉树前序、中序、后序三种遍历方式的分治思想与代码实现,补充满二叉树、完全二叉树等特殊二叉树的定义与数学性质,结合实例推导二叉树节点数、高度等核心公式,零基础也能吃透二叉树的基础理论与核心操作。

阅读时长 :约25分钟
阅读建议

  1. 基础薄弱者:先理解树的递归定义,再掌握二叉树遍历的核心逻辑
  2. 刷题备考者:重点记忆二叉树的5个核心性质及推导过程
  3. 面试冲刺者:熟练掌握前/中/后序遍历的递归实现模板
  4. 查漏补缺者:聚焦满二叉树与完全二叉树的区别及公式推导

一、知识回顾:线性结构 vs 非线性结构

在学习二叉树之前,我们先对比线性结构和非线性结构的核心差异:

结构类型 核心特征 代表结构 数据关系
线性结构 数据呈线性排列,每个元素仅有一个前驱/后继 顺序表、链表、栈、队列 一对一
非线性结构 数据呈层级/网状排列,元素可有多个前驱/后继 树、图 一对多(树)/多对多(图)

简单来说:线性结构是一条线,树结构是一棵树,而二叉树是树结构中最简单、最常用的一种!


二、树的核心概念:什么是倒挂的树?📚

1. 树的定义(递归本质)

树是一种非线性结构,像一棵根朝上、叶朝下的倒挂树,核心特征:

  1. 有且仅有一个根节点(最顶层的节点);
  2. 根节点下有若干棵互不相交的子树,子树同样满足树的定义(递归);
  3. 除根节点外,每个节点有且仅有一个父节点
  4. n个节点的树有n-1条边(无环、无孤立节点)。

2. 树的关键术语(必须熟记)

术语 定义 示例
节点的度 一个节点包含的子树个数 根节点A有6个子节点 → A的度为6
叶子节点(终端节点) 度为0的节点(无子女) B、C、H、I
分支节点(非终端节点) 度不为0的节点 D、E、F、G
父/子节点 若节点X是Y的子树根,则X是Y的父,Y是X的子 A是B的父,B是A的子
兄弟节点 具有相同父节点的节点 B和C是亲兄弟
树的度 树中所有节点的度的最大值 树的度=6(A的度)
节点的层次 根为第1层,子节点为第2层(推荐方式) A在第1层,B在第2层
树的高度(深度) 树中节点的最大层次 若I在第4层 → 树高=4

3. 树的三种表示方式

树的存储需要适配一对多的特性,常见三种方式:

表示方式 核心思路 优缺点
顺序存孩子指针 直接定义多个孩子指针(child1/child2...) 优点:简单;缺点:子节点数固定,浪费空间
左孩子右兄弟(推荐) 每个节点存左孩子+右兄弟指针 优点:适配任意树,空间高效;缺点:需转换思维
双亲表示法 数组存储节点,额外存父节点下标 优点:找父节点快;缺点:找子节点慢(并查集专用)

三、二叉树的核心知识:最简单的树结构🌿

1. 二叉树的定义

二叉树是每个节点最多有2个子节点的树(左子树+右子树),核心特征:

  1. 二叉树的子树有左右之分,不能颠倒(左子树≠右子树);
  2. 任何二叉树可拆分为:根节点 + 左子树 + 右子树(分治思想基础);
  3. 二叉树可以为空(空树也是合法的二叉树)。

2. 二叉树的三种遍历方式(分治算法核心)

遍历是二叉树最核心的操作,本质是分而治之:把遍历整棵树拆成遍历根+左子树+右子树,直到子树为空。

遍历方式 顺序 核心逻辑 示例(树:A(B(D,E),C))
前序遍历(根左右) 根 → 左子树 → 右子树 先访问根,再递归遍历左右 输出:A B D NULL NULL E NULL NULL C NULL NULL(简写ABDEC)
中序遍历(左根右) 左子树 → 根 → 右子树 先遍历左子树,再访问根,最后遍历右 输出:NULL D NULL B NULL E NULL A NULL C NULL(简写DBEAC)
后序遍历(左右根) 左子树 → 右子树 → 根 先遍历左右子树,最后访问根 输出:NULL NULL D NULL NULL E B NULL NULL C A(简写DEBCA)

3. 二叉树遍历的代码实现

(1)二叉树节点结构体定义
c 复制代码
typedef int BTDataType;
typedef struct BinaryTreeNode
{
    struct BinaryTreeNode* left;  // 左孩子指针
    struct BinaryTreeNode* right; // 右孩子指针
    BTDataType data;              // 节点存储的数据
}BTNode;
(2)前序遍历实现
c 复制代码
void PreOrder(BTNode* root)
{
    if (root == NULL) // 递归终止条件:空节点
    {
        printf("NULL ");
        return;
    }
    printf("%c ", root->data); // 1. 访问根节点
    PreOrder(root->left);      // 2. 递归遍历左子树
    PreOrder(root->right);     // 3. 递归遍历右子树
}
(3)中序遍历实现
c 复制代码
void InOrder(BTNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return;
    }
    InOrder(root->left);       // 1. 递归遍历左子树
    printf("%c ", root->data); // 2. 访问根节点
    InOrder(root->right);      // 3. 递归遍历右子树
}
(4)后序遍历实现
c 复制代码
void PostOrder(BTNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return;
    }
    PostOrder(root->left);     // 1. 递归遍历左子树
    PostOrder(root->right);    // 2. 递归遍历右子树
    printf("%c ", root->data); // 3. 访问根节点
}

💡 核心技巧 :三种遍历的代码仅输出根节点的位置不同,记住这个规律,就能快速写出任意遍历的代码!


四、特殊二叉树:满二叉树 vs 完全二叉树🌟

1. 满二叉树(装满的二叉树)

  • 定义:每一层的节点数都达到最大值(第k层有 2 k − 1 2^{k-1} 2k−1个节点);
  • 核心公式(根为第1层):
    • 高度为h的满二叉树,总节点数: N = 2 h − 1 N = 2^h - 1 N=2h−1;
    • 总节点数为N的满二叉树,高度: h = l o g 2 ( N + 1 ) ≈ l o g 2 N h = log_2(N+1) ≈ log_2N h=log2(N+1)≈log2N。

2. 完全二叉树(填不满但连续的二叉树)

  • 定义:① 前h-1层是满的;② 最后一层节点从左到右连续排列(无空缺);
  • 核心公式(根为第1层):
    • 高度为h的完全二叉树,总节点数: 2 h − 1 ≤ N ≤ 2 h − 1 2^{h-1} ≤ N ≤ 2^h - 1 2h−1≤N≤2h−1;
    • 总节点数为N的完全二叉树,高度: l o g 2 ( N + 1 ) ≤ h ≤ l o g 2 N + 1 log_2(N+1) ≤ h ≤ log_2N + 1 log2(N+1)≤h≤log2N+1。

关键区别

  • 满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树;
  • 完全二叉树的最后一层靠左连续,这是和普通二叉树的核心区别。

五、二叉树的5个核心性质(必背)📝

  1. 第n层最多有 2 n − 1 2^{n-1} 2n−1个节点(根为第1层);
  2. 高度为h的二叉树,最大节点数为 2 h − 1 2^h - 1 2h−1;
  3. 任意二叉树:叶子节点数n_0 = 度为 2 的节点数 度为2的节点数 度为2的节点数n_2 + 1 ( ( (n_0 = n_2 + 1);
  4. 满二叉树: N = 2 h − 1 N = 2^h - 1 N=2h−1, h = l o g 2 ( N + 1 ) h = log_2(N+1) h=log2(N+1);
  5. 完全二叉树: 2 h − 1 ≤ N ≤ 2 h − 1 2^{h-1} ≤ N ≤ 2^h - 1 2h−1≤N≤2h−1。

性质3推导(重中之重):

设度为0/1/2的节点数为 n 0 / n 1 / n 2 n_0/n_1/n_2 n0/n1/n2,总结点数 N = n 0 + n 1 + n 2 N = n_0 + n_1 + n_2 N=n0+n1+n2;

总边数 E = n 1 + 2 n 2 E = n_1 + 2n_2 E=n1+2n2(度为1的节点出1条边,度为2的出2条);

又因为 E = N − 1 E = N - 1 E=N−1(除根外,每个节点有1条入边);

联立得: n 0 + n 1 + n 2 − 1 = n 1 + 2 n 2 n_0 + n_1 + n_2 - 1 = n_1 + 2n_2 n0+n1+n2−1=n1+2n2 → 化简得 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1。


六、写在最后

恭喜你!在这一篇中,你已经掌握了二叉树的核心基础:

  • 理解了树的递归定义和关键术语;
  • 掌握了二叉树前/中/后序遍历的递归实现;
  • 区分了满二叉树和完全二叉树,记住了核心公式;
  • 推导并熟记了二叉树的5个核心性质。

二叉树的遍历是所有树结构操作的基础,建议你多敲几遍遍历代码,用纸笔模拟遍历过程------只有真正理解分治思想,才能搞定后续的层序遍历、节点计数、OJ刷题等进阶内容。

下一篇,我们将进入二叉树的实战环节:学习层序遍历、节点计数、平衡二叉树判断等核心操作,把理论转化为解题能力!😜


点赞+收藏+关注,跟着系列内容一步步吃透二叉树!你的支持是我创作的最大动力~👍

相关推荐
无限码力4 分钟前
华为OD机试真题双机位C卷 【运维日志排序】C语言实现
c语言·华为od·华为od机考·华为od机试真题·华为od机试双机位c卷·华为od机考双机位c卷·华为od上机考试
菜鸟233号9 分钟前
力扣416 分割等和子串 java实现
java·数据结构·算法·leetcode
小郭团队23 分钟前
未来PLC会消失吗?会被嵌入式系统取代吗?
c语言·人工智能·python·嵌入式硬件·架构
求梦82028 分钟前
【力扣hot100题】缺失的第一个正数(12)
数据结构·算法·leetcode
黎雁·泠崖42 分钟前
二叉树实战进阶全攻略:从层序遍历到OJ题深度解析
c语言·数据结构·leetcode
散峰而望44 分钟前
【算法竞赛】顺序表和vector
c语言·开发语言·数据结构·c++·人工智能·算法·github
cpp_25011 小时前
B3927 [GESP202312 四级] 小杨的字典
数据结构·c++·算法·题解·洛谷
Cx330❀1 小时前
《C++ 递归、搜索与回溯》第2-3题:合并两个有序链表,反转链表
开发语言·数据结构·c++·算法·链表·面试
独自破碎E1 小时前
链表相加(二)
数据结构·链表
CCPC不拿奖不改名1 小时前
面向对象编程:继承与多态+面试习题
开发语言·数据结构·python·学习·面试·职场和发展