<p>BST节点结构需含int val、TreeNode left、TreeNode right,构造函数显式初始化指针为nullptr;插入函数必须用TreeNode& root引用传参以修改原指针;查找函数根据需求返回bool或TreeNode,且须先判空再访问成员。</p>

怎么写一个能插入和查找的 BST 节点结构
核心是让每个节点知道自己左右子树,且支持比较。别用 std::shared_ptr 开局就套——练习阶段用裸指针更清楚内存流向,也更容易暴露空指针问题。
常见错误现象:segmentation fault 在第一次 insert 就崩,往往是因为根节点初始化为 nullptr 后没在插入时正确赋值,或者递归插入时忘了检查 root == nullptr 就直接访问 root->val。
- 节点结构至少含
int val、TreeNode* left、TreeNode* right - 构造函数里显式初始化
left和right为nullptr,别依赖零初始化(某些编译器或优化级别下不保) - 插入函数必须接受
TreeNode*& root(引用),否则递归中对 root 的修改不会回传到上层
insert 函数为什么一定要用引用传参
因为你要可能把新节点“挂”到原来为空的位置。如果只传 TreeNode* root,那函数内部做的 root = new TreeNode(val) 只改了形参副本,原调用处的指针根本没变——树还是空的。
使用场景:所有需要“可能替换某个子树根”的操作,比如插入、删除、甚至构建过程中的子树拼接。
立即学习“C++免费学习笔记(深入)”;
- 参数写成
void insert(TreeNode*& root, int val),不是TreeNode*也不是TreeNode** - 递归调用时直接传
root->left或root->right,它们本身是指针变量,取地址后自然满足引用要求 - 若误写成值传递,调试时会发现插入后
root始终为nullptr,但函数里明明 new 了
find 查找函数返回 bool 还是 TreeNode*
取决于你要做什么。练习题里说“查找”,通常只要判断存在性,返回 bool 最干净;但如果后续要删节点或打印路径,就得返回指针。二者实现逻辑一样,差别只在最后一行。
性能影响:返回指针多一次地址拷贝,但现代编译器基本优化掉;真正影响性能的是递归深度和重复比较。
- 返回
bool:末尾写return root != nullptr && root->val == val;不够,得先判空再比,否则空指针解引用 - 返回
TreeNode*:直接return root;即可,调用方自己判是否为nullptr - 别在
find里输出 “Found!”——这会让函数职责混乱,也妨碍复用
测试时最容易漏掉的边界情况
不是大数或负数的问题,而是“空树”和“单节点树”这种看似简单却最易出错的情形。很多同学写完跑几个样例就以为 OK,结果一测空输入就段错误。
兼容性影响:这些 case 在 C++11/14/17 下行为一致,但如果你用了 auto 推导又没初始化,不同标准下默认值可能不同。
- 插入第一个节点:确保
root真的被赋值,而不是只在函数栈里 new 了 - 查空树:
find(nullptr, 5)必须安全返回false或nullptr,不能崩溃 - 重复插入相同值:BST 一般不处理重复,要么忽略,要么按题目要求放左/右;但代码里必须有明确分支,不能漏判
==
递归出口和空指针检查,永远比你想的更重要一点。写完别急着测数据,先对着空指针走一遍流程。











