当前位置: 首页 > news >正文

【C++进阶】二叉树进阶

【C++进阶】二叉树进阶

1. 介绍

二叉树在数据结构阶段已经学习过,本节取名"二叉树进阶"主要基于以下考虑:

  1. 承上启下:map和set的实现需要二叉搜索树作为基础
  2. 加深理解:理解二叉搜索树特性有助于掌握更复杂的树结构
  3. 时机合适:部分二叉树面试题难度较大,现在讲解更易吸收
  4. 工具优势:C++相比C语言更方便处理复杂数据结构

本节将通过二叉搜索树对二叉树知识进行系统性总结和提升。

2. 二叉搜索树(Binary Search Tree)

2.1 二叉搜索树概念

二叉搜索树(BST)又称二叉排序树或二叉查找树,它具有以下性质:

  • 非空左子树的所有节点值都小于根节点的值
  • 非空右子树的所有节点值都大于根节点的值
  • 左右子树也都是二叉搜索树
// 二叉搜索树示例
//       8
//      / \
//     3   10
//    / \    \
//   1   6    14
//      / \   /
//     4   7 13

2.2 二叉搜索树基本操作

2.2.1 查找操作

查找过程

  • 从根节点开始比较
  • 目标值 > 当前节点值 → 向右子树查找
  • 目标值 < 当前节点值 → 向左子树查找
  • 目标值 = 当前节点值 → 查找成功
  • 遇到空节点 → 查找失败

时间复杂度:O(h),h为树的高度

2.2.2 插入操作

插入过程

  1. 树为空 → 直接创建根节点
  2. 树不为空 → 按BST性质找到插入位置
  3. 创建新节点并插入到合适位置
// 插入序列:8, 3, 1, 10, 6, 4, 7, 14, 13
// 最终形成的BST如上图所示
2.2.3 删除操作

删除节点分为三种情况:

  1. 叶子节点:直接删除
  2. 只有一个子节点:用子节点替代
  3. 有两个子节点:用前驱或后继节点替代

替换法删除:找到右子树的最小节点(或左子树的最大节点),用其值替换待删除节点,然后删除那个最小(大)节点。

// 删除示例:
// 删除7(叶子节点)→ 直接删除
// 删除14(有一个子节点)→ 用13替代
// 删除3、8(有两个子节点)→ 用前驱/后继替代

2.3 二叉搜索树实现

2.3.1 节点结构定义
template<class T>
struct BSTNode {BSTNode(const T& data = T()): _pLeft(nullptr), _pRight(nullptr), _data(data){}BSTNode<T>* _pLeft;BSTNode<T>* _pRight;T _data;
};
2.3.2 二叉搜索树类定义
template<class T>
class BSTree {typedef BSTNode<T> Node;typedef Node* PNode;
public:BSTree() : _pRoot(nullptr) {}~BSTree();// 查找操作PNode Find(const T& data) {PNode pCur = _pRoot;while (pCur) {if (data == pCur->_data) {return pCur;} else if (data < pCur->_data) {pCur = pCur->_pLeft;} else {pCur = pCur->_pRight;}}return nullptr;}// 插入操作bool Insert(const T& data) {// 树为空的情况if (nullptr == _pRoot) {_pRoot = new Node(data);return true;}// 查找插入位置PNode pCur = _pRoot;PNode pParent = nullptr;while (pCur) {pParent = pCur;if (data < pCur->_data) {pCur = pCur->_pLeft;} else if (data > pCur->_data) {pCur = pCur->_pRight;} else {// 元素已存在return false;}}// 创建新节点并插入pCur = new Node(data);if (data < pParent->_data) {pParent->_pLeft = pCur;} else {pParent->_pRight = pCur;}return true;}// 删除操作bool Erase(const T& data) {if (nullptr == _pRoot) return false;// 查找待删除节点PNode pCur = _pRoot;PNode pParent = nullptr;while (pCur) {if (data == pCur->_data) {break;} else if (data < pCur->_data) {pParent = pCur;pCur = pCur->_pLeft;} else {pParent = pCur;pCur = pCur->_pRight;}}if (nullptr == pCur) return false; // 节点不存在// 情况1:左子树为空if (nullptr == pCur->_pLeft) {if (pCur == _pRoot) {_pRoot = pCur->_pRight;} else {if (pParent->_pLeft == pCur) {pParent->_pLeft = pCur->_pRight;} else {pParent->_pRight = pCur->_pRight;}}delete pCur;}// 情况2:右子树为空else if (nullptr == pCur->_pRight) {if (pCur == _pRoot) {_pRoot = pCur->_pLeft;} else {if (pParent->_pLeft == pCur) {pParent->_pLeft = pCur->_pLeft;} else {pParent->_pRight = pCur->_pLeft;}}delete pCur;}// 情况3:左右子树都不为空else {// 找右子树的最小节点(最左节点)PNode minParent = pCur;PNode minNode = pCur->_pRight;while (minNode->_pLeft) {minParent = minNode;minNode = minNode->_pLeft;}// 用最小值替换当前节点pCur->_data = minNode->_data;// 删除最小节点if (minParent->_pLeft == minNode) {minParent->_pLeft = minNode->_pRight;} else {minParent->_pRight = minNode->_pRight;}delete minNode;}return true;}// 中序遍历void InOrder() {_InOrder(_pRoot);cout << endl;}private:void _InOrder(PNode pRoot) {if (pRoot) {_InOrder(pRoot->_pLeft);cout << pRoot->_data << " ";_InOrder(pRoot->_pRight);}}PNode _pRoot;
};

2.4 二叉搜索树的应用

2.4.1 K模型(纯Key模型)

特点:只存储关键词Key,用于判断元素是否存在。

应用场景

  • 单词拼写检查
  • 敏感词过滤
  • 存在性判断
// 单词拼写检查示例
BSTree<string> spellChecker;
// 加载词库中的所有单词
spellChecker.Insert("apple");
spellChecker.Insert("banana");
spellChecker.Insert("orange");string word;
while (cin >> word) {if (spellChecker.Find(word)) {cout << "拼写正确" << endl;} else {cout << "拼写错误" << endl;}
}
2.4.2 KV模型(Key-Value模型)

特点:存储键值对<Key, Value>,通过Key快速查找Value。

应用场景

  • 英汉词典
  • 单词计数
  • 缓存系统
// KV节点定义
template<class K, class V>
struct BSTNode {BSTNode(const K& key = K(), const V& value = V()): _pLeft(nullptr), _pRight(nullptr), _key(key), _value(value){}BSTNode<K, V>* _pLeft;BSTNode<K, V>* _pRight;K _key;V _value;
};// 英汉词典应用
void TestDictionary() {BSTree<string, string> dict;dict.Insert("string", "字符串");dict.Insert("tree", "树");dict.Insert("left", "左边、剩余");dict.Insert("sort", "排序");string word;while (cin >> word) {auto ret = dict.Find(word);if (ret == nullptr) {cout << "单词不存在: " << word << endl;} else {cout << word << " 的中文翻译: " << ret->_value << endl;}}
}// 单词计数应用
void TestWordCount() {string arr[] = {"苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉"};BSTree<string, int> countTree;for (const auto& str : arr) {auto ret = countTree.Find(str);if (ret == nullptr) {countTree.Insert(str, 1);  // 第一次出现} else {ret->_value++;  // 计数增加}}countTree.InOrder();  // 输出每种水果的出现次数
}

2.5 二叉搜索树的性能分析

2.5.1 性能影响因素

二叉搜索树的性能主要取决于树的高度,而树的高度又受插入顺序影响:

// 最优情况:完全二叉树
// 插入顺序:4, 2, 6, 1, 3, 5, 7
//       4
//      / \
//     2   6
//    / \ / \
//   1  3 5  7// 最差情况:单支树  
// 插入顺序:1, 2, 3, 4, 5, 6, 7
//   1
//    \
//     2
//      \
//       3
//        \
//         4
2.5.2 时间复杂度分析
情况树形态平均查找长度时间复杂度
最优完全二叉树log₂NO(logN)
平均随机树约1.39log₂NO(logN)
最差单支树N/2O(N)
2.5.3 性能优化方向

当二叉搜索树退化为单支树时,性能会急剧下降。为了解决这个问题,后续发展出:

  1. AVL树:严格平衡的二叉搜索树
  2. 红黑树:近似平衡的二叉搜索树(STL map/set的实现基础)
  3. B树系列:多路平衡搜索树(数据库索引基础)

3. 二叉树进阶面试题

以下题目更适合使用C++完成,难度较大但非常经典:

3.1 基础遍历与构造

  1. 二叉树创建字符串

    • 根据二叉树创建字符串
  2. 二叉树的分层遍历

    • 二叉树的层序遍历
  3. 二叉树的锯齿形层次遍历

    • 二叉树层序遍历2

3.2 经典算法问题

  1. 二叉树的最近公共祖先

    • 找到两个节点的最低公共祖先
    • 解法:递归、路径记录
    • 二叉树的最近公共祖先
  2. 二叉搜索树转排序双向链表

    • 将BST转换为有序双向链表
    • 解法:中序遍历+指针调整

3.3 遍历与重构

  1. 前序+中序构造二叉树

    • 根据前序遍历和中序遍历重建二叉树
    • 解法:递归分治
  2. 中序+后序构造二叉树

    • 根据中序遍历和后序遍历重建二叉树
    • 解法:递归分治

3.4 非递归遍历

  1. 二叉树前序遍历(非递归)

    • 使用栈模拟递归过程
  2. 二叉树中序遍历(非递归)

    • 左链入栈法
  3. 二叉树后序遍历(非递归)

    • 双栈法或标记法
http://www.dtcms.com/a/600921.html

相关文章:

  • 【C++】多态(2):纯虚函数多态底层原理
  • C++/Linux小项目:自主shell命令解释器
  • MEMS振荡器MST8012抗冲击设计应对严苛振动环境
  • 【数据结构】常见的排序算法 -- 交换排序
  • Rust与主流编程语言的深度对比分析
  • NebulaChat 框架学习笔记:深入理解 Reactor 与多线程同步机制
  • 网站开发接口网站建设需要什么
  • 聚焦新“新双高计划”,高职学校如何进行数字化转型?
  • 全志V853视频输入驱动框架详解:从VIN模块到虚通道实战
  • 网站建设需要英语吗wordpress笑话主题模板
  • Azure OpenAI GPT-5 PTU 容量规划与弹性配置实践
  • [linux仓库]多线程同步:基于POSIX信号量实现生产者-消费者模型[线程·柒]
  • Linux 内核驱动加载机制
  • C语言编译软件 | 高效选择适合的C语言编译环境
  • 天津 网站策划微信、网站提成方案点做
  • 工业级部署指南:在西门子IOT2050(Debian 12)上搭建.NET 9.0环境与应用部署(进阶篇)
  • 食品网站建设网站定制开发做网站只买一个程序
  • 中小型项目前后端工时对比
  • C# 文件的输入与输出
  • Linux操作系统学习
  • idea创建javaweb项目
  • 【计网】基于OSPF 协议的局域网组建
  • 开发一个小程序花多少钱
  • Ansible入门详解
  • 一体化系统(一)智慧物业管理综合管理——东方仙盟
  • 买虚机送网站建设wordpress google ad
  • 2008 iis配置网站公司做网站需要注意些什么问题
  • vs2013编译C语言 | 探讨如何使用Visual Studio 2013进行C语言编译与调试
  • k8s上分离集群seatunnel部署(生产推荐)
  • 最新版idea2025 配置docker 打包spring-boot项目到生产服务器全流程,含期间遇到的坑