news 2026/6/13 8:16:46

作为一种**动态查找表**,支持在数据频繁变动的情况下高效实现插入、删除和查找操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
作为一种**动态查找表**,支持在数据频繁变动的情况下高效实现插入、删除和查找操作

一、二叉排序树的插入特性

  1. 插入位置:新结点总是作为叶子结点插入。从根结点开始,比较关键字大小,若小于当前结点则进入左子树,否则进入右子树,直到找到空指针位置进行插入。此过程不涉及已有结点的移动,仅修改父结点的孩子指针,类似于有序链表中的“无移动插入”。
  2. 形态依赖输入序列:二叉排序树的结构高度依赖于输入顺序。若输入序列为递增或递减(如12,18,23,45,60),则生成的树将退化为单枝树(即所有结点仅有右孩子或左孩子),导致树的高度达到n,查找、插入、删除操作的时间复杂度退化为O(n),等同于顺序查找。

二、二叉排序树的删除操作
根据被删除结点*p的结构,分为三种情况处理:

  1. p是叶子结点(且非根)

    • 操作简单:直接将其双亲结点*f的相应孩子指针置为空(f->lchild 或 f->rchild = NULL)。
    • 若p为根且是唯一结点,则删除后树为空。
  2. p只有左子树或只有右子树

    • 将p的子树直接链接到其双亲结点*f的对应位置。
      • 例如:若p是f的左孩子且仅有右子树,则执行f->lchild = p->rchild
    • 特殊情况:若p为根结点,则让其子树成为新的根。
  3. p同时有左、右子树

    • 此时不能直接断开连接,需保持中序遍历的有序性。
    • 常用策略:
      • 找到*p的中序后继(即其右子树中的最小结点,也就是右子树中最左边的结点),或
      • 找到*p的中序前驱(即其左子树中的最大结点,也就是左子树中最右边的结点)。
    • 用该结点q的数据值替换p的数据值,然后按上述规则删除q(此时q必定属于前两种情况之一,因为它是极值结点,最多只有一个子树)。

补充:二叉排序树的核心作用

  • 作为一种动态查找表,支持在数据频繁变动的情况下高效实现插入、删除和查找操作。
  • 在理想情况下(树近似平衡),各项操作时间复杂度为O(log n)
  • 实际应用中易受输入序列影响而性能下降,因此常采用平衡二叉树(如AVL树、红黑树)来维持树的平衡,避免退化,从而保证稳定的对数级时间复杂度。
// 示例:二叉排序树节点定义structTreeNode{intval;structTreeNode*left;structTreeNode*right;};

在二叉排序树(BST)中,中序后继是指中序遍历序列中紧跟在指定节点之后的节点。实现中序后继查找需根据节点是否有右子树来分情况处理:


一、有右子树的情况

若目标节点p有右子树,则其中序后继是其右子树中的最左节点(即右子树中值最小的节点)。

步骤

  1. 进入p->right
  2. 沿左孩子一路向下,直到left为空。
structTreeNode*findInorderSuccessor(structTreeNode*p){structTreeNode*current=p->right;while(current&&current->left!=NULL){current=current->left;}returncurrent;}

二、无右子树的情况

p没有右子树,则中序后继在其祖先中寻找:从根开始向下搜索,找到第一个“大于p->val”且“左子树包含p”的祖先节点。

方法:从根出发,用一个指针追踪可能的后继。

structTreeNode*findInorderSuccessorFromRoot(structTreeNode*root,structTreeNode*p){structTreeNode*successor=NULL;while(root!=NULL){if(p->val<root->val){successor=root;// 当前根可能是后继root=root->left;}else{root=root->right;}}returnsuccessor;}

注意:此方法适用于没有父指针的树结构。


三、带父指针的情况(优化)

如果每个节点含有指向父节点的指针(parent),可以向上回溯:

  • p是其父节点的左孩子 → 父节点就是后继。
  • 否则,一直向上找,直到当前节点是其父节点的左孩子为止,该父节点即为后继。
structTreeNode*findInorderSuccessorWithParent(structTreeNode*p){if(p->right){// 有右子树:找右子树中最左节点structTreeNode*current=p->right;while(current->left){current=current->left;}returncurrent;}else{// 无右子树:向上找第一个左分支的祖先structTreeNode*current=p;structTreeNode*parent=current->parent;while(parent!=NULL&&current==parent->right){current=parent;parent=parent->parent;}returnparent;}}

总结

条件中序后继
有右子树右子树的最左节点
无右子树第一个“左子树包含该节点”的祖先

时间复杂度:O(h),h为树高;理想情况下 O(log n),最坏 O(n)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 20:58:57

Zigbee自适应信道选择提升网络稳定性

&#x1f493; 博客主页&#xff1a;塔能物联运维的CSDN主页Zigbee自适应信道选择&#xff1a;从静态到动态的网络稳定性革命目录Zigbee自适应信道选择&#xff1a;从静态到动态的网络稳定性革命 引言&#xff1a;物联网网络的“隐形杀手” 一、核心问题&#xff1a;静态信道选…

作者头像 李华
网站建设 2026/6/12 20:11:35

【稀缺资料】20年经验总结:C++多线程死锁避免的7个不传之秘

第一章&#xff1a;C多线程死锁问题的根源剖析在C多线程编程中&#xff0c;死锁是导致程序停滞不前的常见顽疾。其本质源于多个线程对共享资源的循环等待&#xff0c;且每个线程都持有对方所需资源而不释放&#xff0c;最终陷入永久阻塞状态。死锁的四个必要条件 死锁的发生必须…

作者头像 李华
网站建设 2026/6/12 19:04:17

为什么90%的量子仿真项目失败?C++多qubit内存管理真相曝光

第一章&#xff1a;量子仿真项目失败的根源剖析在推进量子计算应用的过程中&#xff0c;量子仿真项目常被视为验证算法可行性的重要手段。然而&#xff0c;大量项目在实施后期暴露出严重缺陷&#xff0c;甚至以失败告终。深入分析表明&#xff0c;这些失败并非源于单一技术瓶颈…

作者头像 李华
网站建设 2026/6/12 21:09:57

C++26标准下任务队列最大尺寸限制:3个你不知道的底层约束

第一章&#xff1a;C26标准下任务队列最大尺寸限制概述C26 标准在并发与异步编程方面引入了多项增强特性&#xff0c;其中对任务队列&#xff08;task queue&#xff09;的最大尺寸限制进行了规范化定义。这一变更旨在提升系统资源管理的可控性与程序运行的可预测性&#xff0c…

作者头像 李华
网站建设 2026/6/13 2:51:26

C++26即将改变游戏规则:std::execution内存模型详解

第一章&#xff1a;C26 std::execution 内存模型的演进与意义C 标准库在并发编程领域的持续演进中&#xff0c;std::execution 的内存模型设计正迎来关键性升级。C26 对该组件的改进聚焦于提升执行策略与内存序语义之间的协同能力&#xff0c;使开发者能够更精确地控制并行算法…

作者头像 李华
网站建设 2026/6/12 22:55:30

PDF转Word还能保留格式?HunyuanOCR结合排版恢复技术

PDF转Word还能保留格式&#xff1f;HunyuanOCR结合排版恢复技术 在企业日常办公中&#xff0c;一个看似简单却令人头疼的问题反复上演&#xff1a;如何把一份扫描版PDF合同准确、完整地转成可编辑的Word文档&#xff1f;更关键的是——不只是文字要对&#xff0c;格式也得像原…

作者头像 李华