数据结构 | 二叉搜索树 📅 发布时间:2026/7/13 16:00:49 👁️ 浏览次数: 一、二叉搜索树定义1. 标准定义二叉搜索树Binary Search Tree简称BST是在普通二叉树基础上增加有序约束的特殊二叉树由 nn≥0个节点构成。空BST无任何节点非空BST所有节点关键字不允许重复且必须遵守全局有序规则。2. 核心性质整棵树统一有序判定规则任意节点其左子树内所有节点关键字 当前节点关键字 其右子树内所有节点关键字。补充考点对二叉搜索树进行中序遍历输出序列一定是升序该特征是区分普通二叉树与BST最直观判定依据考试高频出题点。3. 专业基础名词直接前驱、直接后继直接前驱 指中序遍历序列里当前节点的前一个节点分三类查找情况情况 1当前节点左子树不为空前驱为左子树中数值最大的节点持续向右遍历左子树末端即可情况 2当前节点左子树为空向上回溯父节点若回溯节点关键字小于当前节点继续向上回溯若回溯节点关键字大于当前节点该节点即为前驱情况 3持续回溯直至父节点为 NULL代表该节点无直接前驱序列第一个元素直接后继 指中序遍历序列里当前节点的下一个节点分三类查找情况情况 1当前节点右子树不为空后继为右子树中数值最小的节点持续向左遍历右子树末端即可情况 2当前节点右子树为空向上回溯父节点若回溯节点关键字小于当前节点继续向上回溯若回溯节点关键字大于当前节点该节点即为后继情况 3持续回溯直至父节点为 NULL代表该节点无直接后继序列最后一个元素二、BST 存储结构1. 存储设计思路普通二叉树二叉链表仅存储左右孩子指针无法向上回溯祖先节点获取前驱、后继逻辑繁琐。本文采用三叉链表存储结构在原有左、右孩子指针基础上新增parent父节点指针支持双向查找大幅简化删除、前驱后继查询逻辑。2. 结构体定义分为两层结构体BSTNode为单个节点单元BSTree封装根节点指针统一管理整棵树。// 保持原样使用前置声明 typedef int ELEMTYPE; // 假设元素类型为int struct BSTNode { ELEMTYPE data; BSTNode* leftchild; BSTNode* rightchild; BSTNode* parent; }; struct BSTree { BSTNode* root; };3. 三叉链表优缺点优点支持向上回溯父节点快速获取前驱、后继删除双分支节点逻辑简化无需递归遍历查找父节点。缺点每个节点多存储一根父指针内存开销更大增删节点时需同步维护parent指针操作不当极易出现野指针、指针指向错乱。适配范围频繁执行删除、查找前驱 / 后继的业务场景仅做单纯查找、遍历场景推荐使用二叉链表节省内存。三、底层工具函数工具函数为业务操作提供底层支撑仅由普通对外函数内部调用不对外提供使用。1. BuyNode 创建新节点实现思路动态分配节点内存使用 C new 创建节点构造函数自动初始化左右孩子、父指针全部置空返回新节点地址。代码实现// 申请新节点 BSTNode* BuyNode() { BSTNode* pnewnode new BSTNode; return pnewnode; }2. Get_PreNode 获取当前节点直接前驱实现思路断言校验节点非空分两大分支处理左子树存在取左子树最大值左子树不存在则向上回溯父节点匹配前驱规则。代码实现BSTNode* Get_PreNode(BSTNode* node) { assert(node ! nullptr); BSTNode* p node; //当前节点左子树不为空找左子树最大值 if (node-leftchild ! nullptr) { p p-leftchild; while (p-rightchild ! nullptr) p p-rightchild; } //当前节点左子树为空向上回溯父节点 else { p p-parent; while (p ! nullptr p-data node-data) { p p-parent; } //循环退出两种情况找到前驱 / 回溯至nullptr无先驱 } return p; }3. Get_NextNode 获取当前节点直接后继实现思路断言校验节点非空分两大分支处理右子树存在取右子树最小值右子树不存在则向上回溯父节点匹配后继规则。代码实现BSTNode* Get_NextNode(BSTNode* node) { assert(node ! nullptr); BSTNode* p node; //当前节点右子树不为空找右子树最小值 if (node-rightchild ! nullptr) { p p-rightchild; while (p-leftchild ! nullptr) p p-leftchild; } //当前节点右子树为空向上回溯父节点 else { p p-parent; while (p! nullptrp-datanode-data) { p p-parent; } //循环退出两种情况找到后继 / 回溯至nullptr无后继 } return p; }四、BST 五大基础操作1. 初始化二叉搜索树实现思路断言校验树结构体指针合法将根指针置空代表空树。代码实现BSTNode* Init_BST(BSTree* pTree) { assert(pTree ! nullptr); pTree-root nullptr; return pTree-root; }2. 插入节点实现思路断言校验树指针单独处理空树场景直接新建节点作为根节点双指针遍历p 遍历查找插入位置pp 记录 p 的父节点遍历过程匹配有序规则待插入值小于当前节点往左走大于则往右走若循环找到等值节点BST不允许重复值直接返回创建新节点根据大小关系挂载至父节点左 / 右分支绑定父子指针代码实现bool Insert_BST(BSTree* pTree, ELEMTYPE val) { assert(pTree ! nullptr); //空树直接创建根节点 if (pTree-root nullptr) { BSTNode* pnewnode BuyNode(); pnewnode-data val; pTree-root pnewnode; pnewnode-parent nullptr; return true; } //双指针遍历寻找插入位置 BSTNode* ppTree-root; BSTNode* ppnullptr; while (p!nullptrp-data!val) { pp p; if (p-data val) p p-leftchild; else p p-rightchild; } //存在重复节点插入失败 if (p ! nullptr p-data val) return false; BSTNode* pnewnode BuyNode(); pnewnode-data val; //挂载到父节点对应分支绑定父指针 if (pnewnode-datapp-data) pp-rightchild pnewnode; else pp-leftchild pnewnode; pnewnode-parent pp; return true; }3. 循环查找节点实现思路断言校验根节点非空指针 p 从根节点开始遍历循环判定当前指针不为空且关键字不匹配按大小规则向左 / 右子树查找循环退出两种分支p 为 nullptr 代表查找失败p 不为 nullptr 代表找到目标节点代码实现BSTNode* Search_BST(BSTNode* root,ELEMTYPE val) { assert(root!nullptr); BSTNode* p root; while (p!nullptrp-data!val) { if (val p-data) { p p-leftchild; } else { p p-rightchild; } } return p; }4. 删除节点1三类删除场景对比零孩子叶子节点直接断开父指针释放当前节点逻辑最简单单孩子仅左 / 右子树唯一子节点直接顶替当前节点位置更新父指针双孩子左右子树均存在无法直接替换子树采用狸猫换太子方案转换为前两种场景2狸猫换太子核心原理直接前驱、直接后继节点的固有特性二者最多只存在单侧子树不存在同时拥有左右两个孩子的情况。将后继节点数据覆盖到待删节点删除逻辑转移至后继节点规避复杂双分支替换操作大幅降低代码复杂度。补充考点前驱、后继均可替换二者效果完全一致工程中常用后继实现。5. 中序遍历打印实现思路利用栈模拟递归流程BST中序遍历输出严格升序tag 标记控制左子树持续入栈逻辑弹出节点打印后处理右子树。代码实现void Show_InOrder_BST(BSTNode* root) { assert(root ! nullptr); std::stackBSTNode* st; st.push(root); bool tag true; while (!st.empty()) { while (tagst.top()-leftchild ! nullptr) { st.push(st.top()-leftchild); } BSTNode* tmp st.top(); st.pop(); printf(%d , tmp-data); if (tmp-rightchild ! nullptr) { st.push(tmp-rightchild); tag true; } else { tag false; } } }五、BST 删除逻辑专项解析1. 仅处理 0 个子节点实现思路先查找目标节点存在且无左右孩子断开父节点对应分支指针释放目标节点内存。代码实现bool Delete_BST0(BSTree* pTree, ELEMTYPE val) { assert(pTree ! nullptr); BSTNode* p Search_BST(pTree-root, val); if (p nullptr) return false; //仅处理叶子节点 if (p-leftchild ! nullptr || p-rightchild ! nullptr) return false; BSTNode* father p-parent; if (father nullptr) pTree-root nullptr; else { if (p-datafather-data) father-leftchild nullptr; else father-rightchild nullptr; } delete p; p nullptr; return true; }2. 处理 0/1 个子节点实现思路查找目标节点判定至多只有单侧子节点取出唯一子节点直接顶替待删节点位置同步修改父指针后释放内存。代码实现bool Delete_BST1(BSTree* pTree, ELEMTYPE val) { assert(pTree ! nullptr); BSTNode* p Search_BST(pTree-root, val); if (p nullptr) return false; //存在两个子节点不处理 if(p-leftchild ! nullptr p-rightchild ! nullptr) return false; BSTNode* father p-parent; //取出唯一存在的子节点 BSTNode* child p-leftchild ! nullptr ? p-leftchild : p-rightchild; if (father nullptr) pTree-root child; else { if (p-data father-data) { father-leftchild child; } else { father-rightchild child; } } delete p; p nullptr; return true; }3. 整合全场景删除实现思路查找待删除节点无节点直接返回场景 1零 / 单分支直接复用单分支删除逻辑场景 2存在左右双孩子执行狸猫换太子获取当前节点直接后继用后继关键字覆盖待删节点数据将删除目标转移至后继节点后继最多仅单分支复用单分支删除逻辑完成释放代码实现bool Delete_BST(BSTree* pTree, ELEMTYPE val) { assert(pTree ! nullptr); BSTNode* p Search_BST(pTree-root, val); if (p nullptr) return false; //零分支直接释放 if (p-leftchild nullptr p-rightchild nullptr) { Delete_BST0(pTree, val); return true; } //双分支节点狸猫换太子 if (p-leftchild ! nullptr p-rightchild ! nullptr) { BSTNode* cat Get_NextNode(p); p-data cat-data; p cat; } //统一处理单分支/转换后的单分支节点 BSTNode* father p-parent; BSTNode* child p-leftchild ! nullptr ? p-leftchild : p-rightchild; if (father nullptr) pTree-root child; else { if (p-data father-data) { father-leftchild child; } else { father-rightchild child; } } delete p; p nullptr; return true; }六、总结1. 结构本质区别普通二叉树无数值约束仅限制节点度≤2BST强制全局有序、数值唯一左小右大是带排序规则的特殊二叉树。2. 遍历特性区别普通二叉树所有遍历无序BST独有中序升序特性可快速完成有序输出先 / 后序遍历不具备有序效果。3. 性能与工程选型理想平衡BST增删查为O(logn)斜树退化O(n)三叉链表适配高频删改、取前驱后继场景普通刷题、简单遍历优先用二叉链表减少指针维护 bug。对比维度普通二叉树二叉搜索树BST节点规则仅限制度≤2无数值大小约束左小右大、数值不重复、全局有序中序遍历序列无序严格升序标志性特征查找效率O(n)平衡 O (logn)、斜树 O (n)核心用途层级存储、遍历排序、检索、动态增删
LogicPoison: Logical Attacks on Graph Retrieval-Augmented Generation——图检索增强生成中的逻辑攻击 论文首次系统性地揭示了图检索增强生成(GraphRAG)系统在逻辑层面的根本性安全漏洞,并提出了一种名为 LOGICPOISON 的新型攻击框架。该框架与传统攻击不同,不注入显性错误信息,而是通过隐蔽地重写语料库中实体间的逻辑连… 2026/7/13 15:58:44
dts-gen与DefinitelyTyped生态:如何贡献高质量类型定义的终极指南 dts-gen与DefinitelyTyped生态:如何贡献高质量类型定义的终极指南 【免费下载链接】dts-gen dts-gen creates starter TypeScript definition files for any module or library. 项目地址: https://gitcode.com/gh_mirrors/dt/dts-gen TypeScript作为JavaScr… 2026/7/13 15:58:44
Trae测评:大半天从Excel到网站效率惊人,但业务逻辑易“翻车”! 数据清洗:它太聪明了每个测评博主电脑里都有个装着待整理Excel的文件夹,我的三个Excel存着2025年初测评的22个AI工具数据,因太乱整理一半放弃。直到Trae刷屏,它是字节出的AI IDE,口号是"用自然语言写代码"。… 2026/7/13 15:56:33
Unity渲染管线简介及几种主要渲染管线的区别 1. 什么是渲染管线?渲染管线(Rendering Pipeline),也称为图形管线,是计算机图形学中将三维场景数据转换为最终二维屏幕图像的一系列处理阶段。在Unity中,渲染管线定义了光照、阴影、材质、后期处理等效果的… 2026/7/13 17:24:21
如何用MiniMax-M2.7-BF16构建多智能体协作系统?Agent Teams实战指南 如何用MiniMax-M2.7-BF16构建多智能体协作系统?Agent Teams实战指南 【免费下载链接】MiniMax-M2.7-BF16 项目地址: https://ai.gitcode.com/hf_mirrors/amd/MiniMax-M2.7-BF16 MiniMax-M2.7-BF16是一款支持Agent Teams多智能体协作的先进AI模型,… 2026/7/13 17:20:19
chocofi焊接与组装指南:新手也能完成的36键分体机械键盘制作 chocofi焊接与组装指南:新手也能完成的36键分体机械键盘制作 【免费下载链接】chocofi Split 36-key keyboard 项目地址: https://gitcode.com/gh_mirrors/ch/chocofi 想要打造一款个性化、符合人体工学的机械键盘吗?chocofi分体式机械键盘可能是… 2026/7/13 17:20:19
Nuke Survival Toolkit:150+专业插件合集,彻底改变你的影视合成工作流 Nuke Survival Toolkit:150专业插件合集,彻底改变你的影视合成工作流 【免费下载链接】NukeSurvivalToolkit_publicRelease public version of the nuke survival toolkit 项目地址: https://gitcode.com/gh_mirrors/nu/NukeSurvivalToolkit_publicRel… 2026/7/13 17:18:17
ChatGPT法律咨询辅助终极验证:在12类高频案由(婚姻/劳动/借贷/知产等)中,它比初级律师快3.8倍,但错判率飙升217%的临界点在哪? 更多请点击: https://kaifayun.com 第一章:ChatGPT法律咨询辅助的实证评估框架 构建可信的法律人工智能辅助系统,需超越主观体验与个案反馈,建立可复现、可度量、可验证的实证评估框架。该框架聚焦三大核心维度:准确性… 2026/7/13 17:18:17
分清门窗品类,2026系统门窗十大品牌盘点 在家装过程中,门窗是居室必不可少的组成部分,直接影响室内采光、通风、隔音与隔热效果,关乎日常居住的舒适体验。当下家装市场主要分为普通组装断桥铝门窗与系统门窗两大类,很多装修业主并不清楚二者的实际区别,选购时… 2026/7/13 17:16:16
HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70+个痛点 HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70个痛点 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾经在Honey Select 2中遇到过… 2026/7/13 0:01:19
语音转文字工具AsrTools:让音频整理变得简单高效 语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text … 2026/7/13 0:03:19
基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_ 基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ 独家界面!不会重复,此项目属于本人原创,若有雷同,均是盗卖,各位买… 2026/7/13 0:05:20
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/13 9:31:08
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/13 2:34:55