数据结构|二叉树高阶进阶-经典算法

在掌握二叉树的创建、递归/非递归遍历、层序遍历、线索化等基础知识点后,我们需要进一步学习二叉树高阶经典算法 。这类题型是算法笔试、面试的核心考点,涵盖树的变换、校验、深度计算、路径查找、公共祖先求解等高频场景。本文结合理论原理,配套完整可运行的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;
}

跑起来吧~

相关推荐
不知名的忻1 小时前
Dijkstra算法(朴素版&堆优化版)
java·数据结构·算法··dijkstra算法
兩尛1 小时前
c++知识点5
开发语言·c++
澈2071 小时前
C++内存管理:new/delete与内存泄漏实战
开发语言·c++·内存分区
星星码️1 小时前
LeetCode刷题简单篇之反转字母
c++·算法·leetcode
其实防守也摸鱼1 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
naturerun2 小时前
螺旋形遍历奇数阶矩阵
c++·算法·矩阵
wuweijianlove2 小时前
算法复杂度的实验估算与误差分布建模的技术7
算法
郝学胜-神的一滴2 小时前
[简化版 GAMES 101] 计算机图形学 08:三角形光栅化上
c++·unity·游戏引擎·godot·图形渲染·opengl·unreal
佳xuan3 小时前
简而言之c++
c++·算法