C++ 怎么实现二叉搜索树 C++ BST插入查找删除代码【数据结构】
发布时间 - 2026-02-01 00:00:00 点击率:次BST节点必须用指针(非值语义),构造函数显式初始化left/right为nullptr;insert需返回新节点并由上层赋值;delete双子节点时须用中序后继替换并递归删除;find推荐返回TreeNode*以支持后续修改。
怎么写一个能用的 BST 节点结构
C++ 实现 BST 的起点不是算法,而是节点定义是否支持后续操作。常见错误是只存 val、不存 left 和 right 指针,或者用裸指针但没初始化为 nullptr,导致未定义行为。
- 必须用指针(
TreeNode*或智能指针),不能用值语义嵌套对象(会无限递归构造) - 构造函数里把
left和right显式设为nullptr,避免野指针 - 如果用
std::unique_ptr,注意移动语义和release()的使用时机
示例最小可用节点:
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};insert 递归实现为什么总崩在空节点插入
崩的原因几乎都是:递归到底层时传入的是局部指针副本,修改它不会影响上层的 root 或子节点指针。比如写成 node = new TreeNode(val),只是改了形参,父节点的 left 或 right 仍是 nullptr。
正确做法只有两种:
- 传指针的引用:
void insert(TreeNode*& node, int val) - 返回新节点地址,由上层赋值:
node->left = insert(node->left, val)
推荐后者,逻辑更清晰、无副作用。示例关键片段:
TreeNode* insert(TreeNode* root, int val) {
if (!root) return new TreeNode(val);
if (val < root->val)
root->left = insert(root
->left, val);
else
root->right = insert(root->right, val);
return root;
}delete 节点时怎么处理有两个子节点的情况
这是 BST 删除最易错的部分。很多人直接删掉目标节点、把左右子树“拼”起来,结果破坏 BST 性质。正确方式是找中序后继(右子树最左节点)或中序前驱(左子树最右节点)来替换。
- 选中序后继更常见:它一定没有左孩子,删它只需处理单子节点或叶子情况
- 替换时不是交换值(虽然可行),而是用后继节点“顶替”被删节点位置,再删后继节点
- 注意:后继节点可能位于右子树深层,删除它时仍要递归调用
deleteNode,不能手动delete
关键逻辑节选:
TreeNode* deleteNode(TreeNode* 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) return root->right;
if (!root->right) return root->left;
// 找右子树最左节点(中序后继)
TreeNode* successor = root->right;
while (successor->left) successor = successor->left;
root->val = successor->val;
root->right = deleteNode(root->right, successor->val); // 递归删后继
}
return root;
}find 查找函数要不要返回指针还是布尔值
取决于使用场景。如果只是判断存在性,返回 bool 最轻量;但如果后续要修改该节点(比如计数、打标记),必须返回 TreeNode*,否则得再查一遍。
- 返回
TreeNode*更通用,且与insert/delete接口风格一致 - 注意:返回
nullptr表示未找到,别和有效节点混淆;调用方必须判空 - 不要用
static局部变量或全局缓存来“优化”查找——BST 本身不保证平衡,缓存失效成本高,反而增加复杂度
示例简洁版:
TreeNode* find(TreeNode* root, int key) {
if (!root || root->val == key) return root;
return key < root->val ? find(root->left, key) : find(root->right, key);
}BST 的难点不在代码行数,而在指针所有权和递归边界。哪怕只漏了一个 return root,或某次 delete 后没置空指针,运行时崩溃就很难定位。写完务必用三类 case 测:空树、单节点、左右子树都非空的根节点删除。
# node
# c++
# 为什么
# Static
# 构造函数
# 局部变量
# 递归
# bool
# int
# void
# 指针
# 数据结构
# 接口
# 形参
# 空指针
# delete
# 对象
# 算法
# 子树
# 的是
# 都是
# 这是
# 很难
# 两种
# 很多人
# 只需
# 设为
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何自定义分页视图?(Pagination示例)
如何在阿里云服务器自主搭建网站?
如何快速选择适合个人网站的云服务器配置?
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
利用 Google AI 进行 YouTube 视频 SEO 描述优化
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】
java中使用zxing批量生成二维码立牌
如何在IIS服务器上快速部署高效网站?
如何快速查询网址的建站时间与历史轨迹?
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
香港服务器如何优化才能显著提升网站加载速度?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
用yum安装MySQLdb模块的步骤方法
php打包exe后无法访问网络共享_共享权限设置方法【教程】
如何用搬瓦工VPS快速搭建个人网站?
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
高防服务器如何保障网站安全无虞?
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
手机软键盘弹出时影响布局的解决方法
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
Laravel如何使用withoutEvents方法临时禁用模型事件
googleplay官方入口在哪里_Google Play官方商店快速入口指南
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
如何基于云服务器快速搭建网站及云盘系统?
微信小程序 五星评分(包括半颗星评分)实例代码
Python高阶函数应用_函数作为参数说明【指导】
如何挑选最适合建站的高性能VPS主机?
如何确保西部建站助手FTP传输的安全性?
如何快速使用云服务器搭建个人网站?
利用vue写todolist单页应用
JavaScript如何实现倒计时_时间函数如何精确控制
Laravel如何使用Vite进行前端资源打包?(配置示例)
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
什么是JavaScript解构赋值_解构赋值有哪些实用技巧
Laravel如何处理文件下载请求?(Response示例)
网站图片在线制作软件,怎么在图片上做链接?
Laravel如何处理异常和错误?(Handler示例)
Laravel怎么上传文件_Laravel图片上传及存储配置
php json中文编码为null的解决办法
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
如何用花生壳三步快速搭建专属网站?
EditPlus中的正则表达式 实战(4)
Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
智能起名网站制作软件有哪些,制作logo的软件?
谷歌Google入口永久地址_Google搜索引擎官网首页永久入口


