treenode结构体最少需包含数据域(如int val)、左子指针(treenode left)和右子指针(treenode right),构造函数应初始化指针为nullptr以防野指针。

为什么不能直接用 std::set 或 std::map?
因为你要控制节点内存布局、支持自定义比较逻辑、需要手动管理指针生命周期,或者在嵌入式/教学场景中避开 STL。标准容器内部虽是红黑树,但不暴露指针操作接口,也无法让你观察插入/查找时的指针跳转过程。
TreeNode 结构体必须包含哪些成员?
最少三个:数据域(如 int val)、左子指针(TreeNode* left)、右子指针(TreeNode* right)。构造函数建议初始化指针为 nullptr,避免野指针:
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
常见错误:忘记初始化指针,导致后续 if (node->left != nullptr) 判断失效或崩溃;误用 new TreeNode() 但未传参,触发默认构造——而你没定义它。
递归插入时如何正确更新父节点指针?
关键不是“返回新节点”,而是“让上一层知道该把谁挂到 left 或 right”。所以插入函数应返回 TreeNode*,由调用方赋值:
- 空树时,直接
return new TreeNode(val) - 值小于当前节点:递归处理左子树,并把结果赋给
root->left = insert(root->left, val) - 值大于当前节点:同理赋给
root->right - 相等时通常忽略(或按需处理重复)
容易踩的坑:insert(root->left, val) 不接返回值,导致新建节点丢失;或在非空子树分支里漏写 return root,造成未定义返回值。
查找和删除为何必须用双重指针或引用传参?
单指针参数(TreeNode* root)只能修改所指对象内容,无法改变调用方的指针变量本身。比如删除根节点时要让外部的 root 指向后继节点,就必须能改它的地址:
- 用二级指针:
void deleteNode(TreeNode** root, int key),删完可写*root = successor - 或用引用:
void deleteNode(TreeNode*& root, int key),更简洁
否则你会写出 root = root->right 这种只改了形参的无效代码。调试时发现删完还是原节点,大概率是这里没传对。
删除最小节点(用于替代被删节点)时,别忘了释放内存:delete minNode,否则泄漏。而释放前必须先保存其左右子指针,因为 delete 后它们就不可访问了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











