发布于2026-07-08 阅读(0)
扫一扫,手机访问
二叉搜索树(BST)的中序前驱与后继查找,是面试和工程中都会碰到的经典操作。很多人一上来就记口诀:“前驱是左子树的最右节点,后继是右子树的最左节点”。但实际情况要复杂得多——因为当前节点可能没有左子树或右子树,这时候就得向上回溯,找祖先节点。下面我们把这层逻辑拆开讲清楚。

中序前驱,说白了就是中序遍历中紧挨着当前节点、比它小的那个节点。它不一定在左子树里。当节点有左子树时,前驱确实是左子树中最右边的那个节点(一路向右走到头);但如果节点没有左子树呢?那就只能向上走,找到第一个“它是父节点的右孩子”的祖先节点,那个父节点就是前驱。
举个例子:一棵BST中,根节点如果压根没有左子树,它的前驱只能从祖先里找——从根往上回溯,直到某个节点是它父节点的右孩子,此时父节点就是目标。如果一路回溯到根都没找到(比如根节点本身就是最左节点),那就没有前驱。
实操建议:
parent 指针向上回溯,找第一个满足「该节点是其父节点右孩子」的祖先,那个父节点就是前驱。right 直到为空)。parent 指针,否则无法高效向上查找。如果没有 parent,就只能先做一次完整中序遍历,把节点存进数组再查索引,时间复杂度 O(n)。后继的逻辑和前驱正好对称。中序后继就是中序遍历中紧挨着当前节点、比它大的那个节点。依然分两种情况:
left 直到为空)。parent 一路向上都是父节点的右孩子),那后继就不存在,返回 nullptr。这里有个常见坑:写代码时容易崩溃,出现 Segmentation fault。十有八九是在访问 parent->left 或 parent->right 之前没判空。建议每次使用 parent 之前先检查是否为 nullptr,这个习惯能省下不少调试时间。
很多教材实现的BST节点结构并不带 parent 字段。这时候想用 O(h) 时间完成查询基本没戏,只能降级处理。有哪些思路?
std::vector 存节点指针),然后在线性表里用二分查找或线性扫描找目标索引。空间 O(n),时间 O(n),适合离线批量查询的场景。parent 字段。虽然改数据结构麻烦点,但比每次遍历划算得多。答案是“是”,但人家不是你那小手写的简单BST。libstdc++ 和 libc++ 里的 std::set 底层是红黑树,std::next(it) 和 std::prev(it) 内部实现的正是前驱/后继操作,且常数均摊。
几个值得注意的点:
parent 指针,而是利用红黑树的节点结构(颜色位、子节点关系)在 O(log n) 时间内完成,且没有额外空间开销。std::set::iterator 是封装过的,不能解引用成原始节点指针来操作。std::set 里插入相同序列,再用相同 key 查后继,输出地址或值来比对。最后说一句容易被忽略的事:手写BST里,parent 指针的维护必须贯穿所有修改操作——插入、删除,缺一不可。漏掉任何一处对 parent 指针的更新,前驱/后继查询就会静默出错,这种 bug 极难排查。所以要么用严谨的测试覆盖,要么干脆考虑带 parent 字段的工程实现。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8