0. 前言
我们彻底吃透了线性数据结构全家桶 :顺序表、链表、栈、队列。所有结构都遵循"一维线性排布",数据之间只有简单的前后关系,能够解决批量存储、顺序调度、逆序匹配、层级缓冲等基础问题,但无法表达一对多、层级、分支、嵌套关联关系。
从今天开始,我们正式告别线性结构,迈入非线性树形结构 的核心领域。树是算法体系中承上启下的超级重点,而二叉树是所有树形结构的基石。后续的二叉搜索树、平衡树、红黑树、堆、哈夫曼树、字典树,全部建立在二叉树的基础逻辑之上。
二叉树也是笔试、面试、算法刷题的高频必考模块。LeetCode 树类题目占比极高,递归遍历、层序遍历、树的深度、路径、翻转、对称判断、构造二叉树,是入门进阶的必刷基础题型。
很多初学者学树最大的问题:只会背遍历代码,不懂树的核心性质、分不清满二叉树与完全二叉树、不理解递归遍历的底层逻辑、不会迭代写法、无法根据遍历序列还原二叉树。
今天我们从零零基础、无门槛精讲二叉树完整体系,从基础名词、树形分类、数学性质、结点封装、递归三序遍历、队列层序遍历、完整可运行代码、刷题模型、工程场景、面试满分问答全方位吃透,筑牢树形结构的第一块核心基石。
1. 树通用基础概念(必背名词)
在深入二叉树之前,我们先统一树结构的标准术语,所有树形结构通用,面试填空题、选择题高频考点。
结点:存储数据与分支关系的基本单元;
根结点:树的最顶层结点,无父结点,一棵树有且仅有一个根;
父结点/子结点:上层结点为父,下层分支结点为子;
叶子结点:无任何子结点的终端结点;
度:一个结点拥有的子结点个数;
树的度:整棵树所有结点的最大度数;
层次:根结点为第一层,向下逐层递增;
深度/高度:树的最大层次数,代表树的纵向长度;
子树:任意一个结点及其所有后代结点构成的独立树形结构。
2. 二叉树严格定义与核心特性
2.1 二叉树定义
二叉树是每个结点最多拥有两个子结点的有序树 ,子结点严格区分左子树、右子树,顺序不可颠倒。
核心约束:
-
每个结点度数只能是 0、1、2;
-
左右子树严格有序,左、右单独存在时属于不同二叉树;
-
二叉树可以为空,空树合法。
2.2 二叉树五大基本形态
空二叉树、单结点树、仅有左子树、仅有右子树、左右子树齐全,所有二叉树均由这五种形态组合而成。
3. 三类核心二叉树(面试必考区分)
很多面试翻车点:混淆满二叉树、完全二叉树、普通二叉树的定义,下面给出教科书级满分定义。
3.1 满二叉树
每一层的结点数都达到最大值,所有叶子结点在同一层,所有非叶子结点度数均为2,没有缺结点、没有空分支。结构极度规整。
3.2 完全二叉树(重点)
对一棵二叉树按层序从左到右编号,所有编号与同深度满二叉树完全一致。简单理解:除最后一层外,其余层全部满;最后一层结点全部靠左连续排列,无空缺、无跳位。
✅ 关键结论:满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。
3.3 平衡二叉树
左右子树高度差不超过1,且左右子树均为平衡二叉树,保证树不会退化成链表,后续平衡树、AVL树、红黑树均基于此特性优化。
4. 二叉树黄金数学性质(笔试秒杀公式)
以下公式为考试、刷题、面试高频结论,无需推导,直接背诵使用。
-
第 i 层最大结点数:2\^{i-1}
-
深度为 k 的二叉树最大结点总数:2\^k - 1
-
任意二叉树:度0结点数 = 度2结点数 + 1(万能公式,必考)
-
深度为k的满二叉树,叶子结点数:2\^{k-1}
-
n个结点的完全二叉树,深度为:\\lfloor log_2n \\rfloor + 1
5. 二叉树结点结构封装
统一刷题与工程标准结点结构,包含数据、左孩子指针、右孩子指针,所有二叉树算法均基于此结构实现。
cpp
// 二叉树结点结构
struct TreeNode
{
int val;
TreeNode* left; // 左孩子
TreeNode* right; // 右孩子
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
6. 二叉树核心:三大递归遍历(重中之重)
遍历是二叉树所有算法的基础,前序、中序、后序区别仅在于「根结点访问时机」,左右子树永远是先左后右。
前序遍历:根 ➜ 左 ➜ 右(先访问当前根)
中序遍历:左 ➜ 根 ➜ 右(中间访问当前根)
后序遍历:左 ➜ 右 ➜ 根(最后访问当前根)
6.1 三序遍历完整递归代码
cpp
#include <iostream>
using namespace std;
// 结点定义
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
// 前序遍历
void preOrder(TreeNode* root)
{
if(!root) return;
cout << root->val << " "; // 根
preOrder(root->left); // 左
preOrder(root->right); // 右
}
// 中序遍历
void inOrder(TreeNode* root)
{
if(!root) return;
inOrder(root->left); // 左
cout << root->val << " "; // 根
inOrder(root->right); // 右
}
// 后序遍历
void postOrder(TreeNode* root)
{
if(!root) return;
postOrder(root->left); // 左
postOrder(root->right); // 右
cout << root->val << " "; // 根
}
// 测试构建简单二叉树
int main()
{
// 构建样例树
// 1
// \
// 2
// /
// 3
TreeNode* root = new TreeNode(1);
root->right = new TreeNode(2);
root->right->left = new TreeNode(3);
cout << "前序遍历:";
preOrder(root);
cout << endl;
cout << "中序遍历:";
inOrder(root);
cout << endl;
cout << "后序遍历:";
postOrder(root);
cout << endl;
return 0;
}
6.2 遍历核心考点
-
递归终止条件:结点为空直接返回,是防止递归死循环的核心;
-
三序遍历访问路径完全一致,仅打印时机不同;
-
二叉搜索树中序遍历结果有序,是后续搜索树刷题的核心依据。
7. 层序遍历(广度优先 BFS)
递归遍历是深度优先,层序遍历是广度优先,依靠队列实现,从上到下、从左到右逐层输出,是完全二叉树、树形分层问题的核心解法。
cpp
#include <queue>
void levelOrder(TreeNode* root)
{
if(!root) return;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
TreeNode* cur = q.front();
q.pop();
cout << cur->val << " ";
// 先左后右入队,保证顺序
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
}
核心逻辑:队列存储每一层结点,逐层出队、子结点逐层入队,实现分层遍历,时间复杂度稳定 O(n)。
8. 二叉树经典刷题模型
所有二叉树算法,全部基于四种遍历衍生,提前掌握模型,刷题事半功倍。
1. 深度优先模型(递归三序)
适合:树的深度计算、结点统计、路径查找、树的翻转、对称树判断。
2. 广度优先模型(层序遍历)
适合:层平均值、每层最大值、树的宽度、完全二叉树校验、分层输出。
3. 分治模型
将大问题拆分为左子树、右子树子问题,递归求解后合并结果,是树类最优解问题的核心思想。
9. 工程真实应用场景
-
文件系统:磁盘目录层级结构,文件夹嵌套树形存储;
-
编译语法树:编译器解析代码生成抽象语法树AST;
-
索引结构:数据库索引、字典树、检索树底层依托树形;
-
AI决策树:分支判断、状态决策、博弈搜索;
-
最优编码:哈夫曼树实现文件压缩编码。
10. 高频坑点汇总
-
忽略空树判断:递归无终止条件,直接栈溢出崩溃;
-
混淆左右子树顺序:遍历、构造树时颠倒左右,结果完全错误;
-
满二叉树与完全二叉树概念混淆:选择题、判断题高频丢分;
-
层序遍历入队顺序颠倒:先右后左,破坏从左到右规则;
-
不会区分遍历序列:只背代码,无法根据序列还原树形结构。
11. 面试满分问答(必背)
Q1:简述二叉树的定义与核心特性?
二叉树是每个结点最多两个子结点的有序树,严格区分左右子树,拥有五种基本形态,支持深度优先三序遍历与广度优先层序遍历,是所有树形结构的基础。
Q2:满二叉树和完全二叉树的区别?
满二叉树每层结点全部满,叶子结点统一在最底层;完全二叉树仅要求除最后一层外全满,最后一层结点靠左连续排列。满二叉树一定是完全二叉树,反之不成立。
Q3:二叉树三序遍历的区别?
唯一区别是根结点的访问时机:前序根优先、中序根居中、后序根最后,左右子树始终遵循先左后右的遍历顺序。
Q4:递归遍历和层序遍历的适用场景?
递归三序遍历属于深度优先,适合求解树深度、路径、结点统计;层序遍历属于广度优先,适合分层统计、树宽度、完全二叉树校验等场景。
Q5:任意二叉树度0与度2结点的关系?
叶子结点数(度0) = 度2结点数 + 1,是二叉树通用万能结论。
12. 全文总结
今天我们正式踏入非线性结构领域,完整吃透了二叉树零基础全套体系。从树的基础名词、二叉树定义、三类树形分类、数学核心公式、结点封装、三序递归遍历、队列层序遍历、刷题模型、工程场景与面试考点全方位覆盖。
二叉树是树形结构的绝对基石,只有彻底掌握遍历逻辑与树形特性,后续才能轻松攻克二叉搜索树、平衡树、堆、哈夫曼树等高阶结构。