
在掌握二叉树的创建、递归/非递归遍历、层序遍历、线索化等基础知识点后,我们需要进一步学习二叉树高阶经典算法 。这类题型是算法笔试、面试的核心考点,涵盖树的变换、校验、深度计算、路径查找、公共祖先求解等高频场景。本文结合理论原理,配套完整可运行的C++实操代码,实现理论与实战结合。
一、前置基础:通用二叉树节点定义
所有高阶算法均基于标准二叉树节点结构实现,统一节点定义,保证代码通用性,同时引入所需头文件,支持直接编译运行。
cpp
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
// 通用二叉树节点结构体
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
// 构造函数
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
二、高阶实操一:二叉树最大/最小深度
1. 理论原理
二叉树的最大深度:根节点到最远叶子节点的最长路径上的节点数,核心思路为递归分治,分别求解左右子树深度,取最大值+1(当前节点)。
二叉树的最小深度:根节点到最近叶子节点的最短路径节点数,需特殊处理单侧子树为空的情况,避免误判深度。
2. C++完整实操代码
cpp
// 二叉树最大深度(递归版)
int maxDepth(TreeNode* root) {
// 空树深度为0
if (root == nullptr) return 0;
// 左右子树最大深度 + 当前节点
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
// 二叉树最小深度(递归版)
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;
// 左右子树都为空,当前节点为叶子节点,深度为1
if (root->left == nullptr && root->right == nullptr) return 1;
// 左子树为空,仅遍历右子树
if (root->left == nullptr) return minDepth(root->right) + 1;
// 右子树为空,仅遍历左子树
if (root->right == nullptr) return minDepth(root->left) + 1;
// 左右子树均存在,取最小值
return min(minDepth(root->left), minDepth(root->right)) + 1;
}
三、高阶实操二:翻转二叉树(镜像二叉树)
1. 理论原理
翻转二叉树是经典基础高阶算法,核心逻辑:遍历二叉树,交换每个节点的左右子节点。可通过递归、迭代两种方式实现,是很多复杂树算法的前置基础。
2. C++完整实操代码
cpp
// 递归实现:翻转二叉树
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) return nullptr;
// 交换当前节点的左右子树
TreeNode* temp = root->left;
root->left = invertTree(root->right);
root->right = invertTree(temp);
return root;
}
// 层序迭代实现:翻转二叉树(非递归)
TreeNode* invertTreeByQueue(TreeNode* root) {
if (root == nullptr) return nullptr;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* cur = q.front();
q.pop();
// 交换左右节点
swap(cur->left, cur->right);
// 子节点入队,继续遍历
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
return root;
}
四、高阶实操三:对称二叉树校验
1. 理论原理
判断一棵二叉树是否轴对称,核心条件:根节点的左右子树互为镜像。镜像规则:两个根节点值相等、左树的左子树与右树的右子树对称、左树的右子树与右树的左子树对称。
2. C++完整实操代码
cpp
// 辅助函数:判断两个子树是否互为镜像
bool isMirror(TreeNode* left, TreeNode* right) {
// 两个节点均为空,对称
if (left == nullptr && right == nullptr) return true;
// 一个空一个非空,不对称
if (left == nullptr || right == nullptr) return false;
// 值相等,且交叉子树对称
return (left->val == right->val)
&& isMirror(left->left, right->right)
&& isMirror(left->right, right->left);
}
// 主函数:判断二叉树是否对称
bool isSymmetric(TreeNode* root) {
if (root == nullptr) return true;
return isMirror(root->left, root->right);
}
五、高阶实操四:路径总和问题
1. 理论原理
给定一个目标值,判断二叉树中是否存在根节点到叶子节点的路径,路径上所有节点值之和等于目标值。核心思路:递归递减目标值,遍历至叶子节点时判断是否匹配。
2. C++完整实操代码
cpp
bool hasPathSum(TreeNode* root, int targetSum) {
// 空树无路径
if (root == nullptr) return false;
// 叶子节点:判断剩余值是否等于当前节点值
if (root->left == nullptr && root->right == nullptr) {
return targetSum == root->val;
}
// 递归遍历左右子树,目标值减去当前节点值
return hasPathSum(root->left, targetSum - root->val)
|| hasPathSum(root->right, targetSum - root->val);
}
六、高阶实操五:二叉树最近公共祖先(LCA)
1. 理论原理
给定二叉树的两个节点,找到它们最深的公共祖先节点。核心递归逻辑:当前节点为空/等于目标节点,直接返回;左右子树分别查找,左右均有结果则当前节点为公共祖先,单侧有结果则向上传递。
2. C++完整实操代码
cpp
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 终止条件:空节点 / 匹配到目标节点
if (root == nullptr || root == p || root == q) return root;
// 递归查找左右子树
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
// 左右都找到,当前节点为公共祖先
if (left != nullptr && right != nullptr) return root;
// 单侧找到,返回单侧结果
return left == nullptr ? right : left;
}
七、完整测试主函数(可直接运行)
整合所有算法,构建测试二叉树,验证所有高阶功能,复制代码即可直接编译运行。
cpp
// 前序遍历打印二叉树(测试用)
void prePrint(TreeNode* root) {
if (root == nullptr) return;
cout << root->val << " ";
prePrint(root->left);
prePrint(root->right);
}
int main() {
// 构建测试二叉树
/*
1
/ \
2 3
/ \
4 5
*/
TreeNode* 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);
// 测试最大最小深度
cout << "二叉树最大深度:" << maxDepth(root) << endl;
cout << "二叉树最小深度:" << minDepth(root) << endl;
// 测试对称判断
cout << "是否为对称二叉树:" << (isSymmetric(root) ? "是" : "否") << endl;
// 测试路径总和
cout << "是否存在路径和为8:" << (hasPathSum(root, 8) ? "是" : "否") << endl;
// 测试翻转二叉树
TreeNode* invertRoot = invertTree(root);
cout << "翻转后前序遍历:";
prePrint(invertRoot);
cout << endl;
return 0;
}
跑起来吧~
