0

0

c++中如何实现二叉搜索树的删除节点操作_c++树结构维护算法【详解】

尼克

尼克

发布时间:2026-01-18 09:54:08

|

796人浏览过

|

来源于php中文网

原创

bst删除节点需分三类处理:叶子节点直接删除并置空父指针;仅一子节点则用子节点顶替并修正父节点对应指针;两子节点须用中序后继替换值后递归删除后继,且后继可能带右子树需正确挂载。

c++中如何实现二叉搜索树的删除节点操作_c++树结构维护算法【详解】

删除节点时如何处理三种子节点情况

二叉搜索树(BST)删除节点的核心难点在于:被删节点的子节点数量不同,修复方式完全不同。不能只靠“找到就删”,必须按 node->left == nullptr && node->right == nullptrnode->left == nullptr || node->right == nullptrnode->left != nullptr && node->right != nullptr 三类分别处理。

常见错误是统一用中序后继替换却忘了更新后继的父指针,或在单子节点情况下直接用子节点覆盖却未修正其父节点的对应指针(比如该节点是父节点的左子还是右子没判断清楚)。

  • 叶子节点:直接 delete 并置空父节点对应指针
  • 仅一个子节点:用该子节点“顶替”被删节点位置,注意修改父节点的 leftright 指针
  • 两个子节点:必须用中序后继(右子树最左节点)或中序前驱(左子树最右节点)替换值,再递归删除那个后继/前驱节点——它必然是叶子或仅一子,否则逻辑不闭环

中序后继查找与链接断开的关键细节

选中序后继(而非前驱)是惯例,但实现时容易忽略:后继节点可能有右子树。此时不能直接把后继的右子树丢弃,而要将其挂到后继原父节点的左指针上(因为后继是“最左”,所以它一定是其父节点的左子)。

更隐蔽的问题是:若后继节点就是待删节点的右子(即右子树无左分支),那么后继的父节点就是待删节点本身,此时直接用 node->right 替换即可,无需额外断链。

立即学习C++免费学习笔记(深入)”;

MeloCool
MeloCool

AI歌曲生成器 - 歌词转歌曲AI音乐制作器在线工具

下载
TreeNode* findSuccessor(TreeNode* root) {
    root = root->right;
    while (root->left != nullptr) {
        root = root->left;
    }
    return root;
}
<p>TreeNode<em> deleteNode(TreeNode</em> root, int key) {
if (!root) return nullptr;
if (key < root->val) {
root->left = deleteNode(root->left, key);
} else if (key > root->val) {
root->right = deleteNode(root->right, key);
} else {
if (!root->left && !root->right) {
delete root;
return nullptr;
} else if (!root->left) {
TreeNode<em> tmp = root->right;
delete root;
return tmp;
} else if (!root->right) {
TreeNode</em> tmp = root->left;
delete root;
return tmp;
} else {
TreeNode* succ = findSuccessor(root);
root->val = succ->val;
// 关键:递归删除 succ,不是 root->right = succ->right
root->right = deleteNode(root->right, succ->val);
}
}
return root;
}

递归实现中为什么必须返回 TreeNode*

因为 C++ 中函数参数默认传值,TreeNode* root 是指针的副本,修改形参本身(如 root = nullptr)不影响调用方的指针。只有通过返回新根并由上层赋值,才能真正切断旧连接。

典型反例:有人写 if (isLeaf) { delete root; root = nullptr; },这只会让函数内局部变量 root 变成空,上层调用处的指针仍指向已释放内存,后续访问必然崩溃。

  • 每次递归调用都必须接收返回值:root->left = deleteNode(root->left, key)
  • 叶子节点删除后必须返回 nullptr,否则父节点的 left/right 仍指向已释放地址
  • 单子节点场景下,返回子节点指针,相当于“把子节点提到当前位”,同时自动解绑原父子关系

非递归删除的指针维护陷阱

手动维护父指针的迭代写法看似直观,但极易出错:需同时追踪 currentparent,且必须在每步移动前记录谁是父节点。尤其当删除的是根节点时,parentnullptr,所有指针修正逻辑都要分支处理。

更大的坑在于:找到后继后,要从后继的父节点“摘下”它。如果后继就是 current->right,那它的父节点是 current;否则父节点在右子树中,得重新查找——这会让代码膨胀且难验证。

除非有明确性能约束(如空间极度受限),否则递归更安全。迭代版本唯一优势是可避免最坏 O(h) 栈深度,但实际 BST 若不平衡,h 可能接近 n,此时先做平衡化(如转 AVL)比硬写迭代删除更治本。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

845

2023.08.22

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

434

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

601

2023.08.10

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

287

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

222

2023.12.29

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

489

2023.08.14

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

3

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

21

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

108

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 7.3万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 21.3万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 13.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号