news 2026/5/9 21:17:49

二叉排序树(Binary Search Tree, BST)是一种重要的数据结构,具有良好的查找、插入和删除性能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二叉排序树(Binary Search Tree, BST)是一种重要的数据结构,具有良好的查找、插入和删除性能

二叉排序树(Binary Search Tree, BST)是一种重要的数据结构,具有良好的查找、插入和删除性能。以下是针对你提出的问题的详细解答:


1. 二叉排序树的查找算法(SearchBST)

// 定义二叉树节点结构typedefstructBSTNode{intdata;structBSTNode*left,*right;}BSTNode,*BSTree;/** * 在二叉排序树中查找关键字 key * @param T: 当前树根节点 * @param key: 要查找的关键字 * @param father: 记录查找路径中的父节点(用于插入时定位) * @return: 找到返回该节点,否则返回 NULL */BSTNode*SearchBST(BSTree T,intkey,BSTNode*father){if(T==NULL)returnNULL;// 空树则未找到if(key==T->data)returnT;// 找到目标节点elseif(key<T->data)returnSearchBST(T->left,key,T);// 向左子树查找,当前节点成为潜在父亲elsereturnSearchBST(T->right,key,T);// 向右子树查找,当前节点成为潜在父亲}

说明father参数通过递归传递,记录最后访问的非空节点(即插入位置的父节点),便于后续插入操作。


2. 二叉排序树的构造过程

构造基于逐个插入元素的过程,遵循以下规则:

  • 若树为空,则第一个节点为根;
  • 对每个新元素,从根开始比较:
    • 小于当前节点 → 进入左子树;
    • 大于当前节点 → 进入右子树;
    • 直到遇到空指针位置进行插入。
示例:{46, 25, 54, 13, 29, 91}
插入顺序操作
46创建根节点
2525 < 46 → 插入 46 的左子树
5454 > 46 → 插入 46 的右子树
1313 < 46 → 左;13 < 25 → 插入 25 的左子树
2929 < 46 → 左;29 > 25 → 插入 25 的右子树
9191 > 46 → 右;91 > 54 → 插入 54 的右子树

最终形成的树结构如下(缩进表示层次):

46 / \ 25 54 / \ \ 13 29 91

3. 二叉排序树的插入算法(InsertBST)

/** * 插入新关键字 newkey 到二叉排序树 * @param root: 指向根节点的指针(可能需要修改根) * @param newkey: 新的关键字 * @return: 成功返回 0,已存在返回 -1 */intInsertBST(BSTree*root,intnewkey){BSTNode*parent=NULL;BSTNode*found=SearchBST(*root,newkey,NULL);if(found!=NULL)return-1;// 关键字已存在,不允许重复// 创建新节点BSTNode*newNode=(BSTNode*)malloc(sizeof(BSTNode));if(!newNode)return-1;// 内存分配失败newNode->data=newkey;newNode->left=newNode->right=NULL;// 查找插入位置及其父节点BSTNode*current=*root;parent=NULL;while(current!=NULL){parent=current;if(newkey<current->data)current=current->left;elsecurrent=current->right;}// 插入新节点if(parent==NULL){*root=newNode;// 树为空,新节点作为根}elseif(newkey<parent->data){parent->left=newNode;}else{parent->right=newNode;}return0;// 插入成功}

注意:使用双重指针BSTree* root是为了在根为空时能正确修改根节点。


二叉排序树的特点总结

特性说明
有序性中序遍历可得有序序列,支持高效查找
平均时间复杂度查找/插入/删除:O(log n)(平衡情况下)
最坏情况当输入有序时,退化为链表,时间复杂度变为 O(n)
结构依赖插入顺序不同插入顺序生成不同形状的树,影响效率
优化方向使用平衡二叉树(如 AVL、红黑树)避免退化

要验证一棵二叉树是否为二叉排序树(BST),最有效的方法是利用其核心性质:中序遍历的结果必须是一个严格递增的序列


✅ 验证方法:基于中序遍历

我们可以通过中序遍历二叉树,并在访问节点时检查当前节点的值是否大于前一个访问的节点值。如果是,则继续;否则不是 BST。

使用非递归或递归方式均可,但关键是要维护“前驱节点”的值进行比较。


🟩 方法一:递归 + 引用前驱值(推荐)
#include<stdio.h>#include<stdlib.h>#include<limits.h>// 二叉树节点定义typedefstructTreeNode{intval;structTreeNode*left;structTreeNode*right;}TreeNode;// 辅助函数:判断是否为BSTboolisValidBSTHelper(TreeNode*root,long*prev){if(root==NULL)returntrue;// 左子树必须是BSTif(!isValidBSTHelper(root->left,prev))returnfalse;// 当前节点必须大于前一个节点值if(root->val<=*prev)returnfalse;*prev=root->val;// 更新前驱值// 右子树必须是BSTreturnisValidBSTHelper(root->right,prev);}/** * 判断是否为二叉排序树 * @param root: 根节点 * @return: 是返回 true,否则返回 false */boolisValidBST(TreeNode*root){longprev=LONG_MIN;// 初始化为最小长整型,避免越界returnisValidBSTHelper(root,&prev);}

说明

  • 使用long类型防止int最小值被误判。
  • prev记录中序遍历过程中上一个访问节点的值。
  • 所有节点必须满足当前值 > prev,即严格递增

🟨 方法二:中序遍历存数组后判断有序性(简单直观)
voidinorder(TreeNode*root,int*arr,int*idx){if(root==NULL)return;inorder(root->left,arr,idx);arr[(*idx)++]=root->val;inorder(root->right,arr,idx);}boolisSorted(int*arr,intn){for(inti=1;i<n;i++)if(arr[i]<=arr[i-1])returnfalse;returntrue;}boolisValidBST_Array(TreeNode*root){intarr[10000],idx=0;inorder(root,arr,&idx);returnisSorted(arr,idx);}

缺点:需要额外 O(n) 空间,效率较低,适合教学理解。


⚠️ 注意事项

  1. 必须是“严格递增”:不允许相等(除非题目允许重复元素且规定右子树 ≥ 根)。
  2. 不能只比较父子关系:例如:
    5 / \ 3 8 / \ 2 6 / 4
    虽然每个父节点与子节点满足大小关系,但左子树中的4 < 5却出现在右分支中 —— 实际上这棵树仍是合法的?不!此例需具体分析路径上下界!

👉 更高级写法可用带上下界的递归来处理跨层约束。


🔍 带上下界的递归验证法(更严谨)

boolvalidate(TreeNode*node,longminVal,longmaxVal){if(node==NULL)returntrue;if(node->val<=minVal||node->val>=maxVal)returnfalse;returnvalidate(node->left,minVal,node->val)&&validate(node->right,node->val,maxVal);}boolisValidBST_Bound(TreeNode*root){returnvalidate(root,LONG_MIN,LONG_MAX);}

此方法可防止某些“局部满足但全局违反”的情况。


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

C++26 constexpr深度优化技巧:90%开发者忽略的3个关键点

第一章&#xff1a;C26 constexpr 编译优化的演进与核心价值C26 对 constexpr 的进一步深化标志着编译期计算能力迈向新的里程碑。该标准扩展了 constexpr 的适用场景&#xff0c;允许更多运行时行为在编译期求值&#xff0c;从而显著提升程序性能与安全性。编译期计算能力的全…

作者头像 李华
网站建设 2026/5/9 21:14:00

【C++26性能革命】:constexpr如何让程序运行快10倍?真相曝光

第一章&#xff1a;C26 constexpr性能革命的背景与意义C 语言自诞生以来&#xff0c;始终致力于在编译期优化和运行时性能之间寻求突破。随着 C26 标准的临近&#xff0c;constexpr 的能力将迎来一次根本性跃迁&#xff0c;被称为“constexpr 性能革命”。这一变革不仅扩展了常…

作者头像 李华
网站建设 2026/4/22 3:23:17

React组件化调用OCR服务?基于HunyuanOCR的实践构想

React组件化调用OCR服务&#xff1f;基于HunyuanOCR的实践构想 在企业数字化转型加速的今天&#xff0c;文档处理正从“人工录入”迈向“智能提取”。一张身份证、一份发票、一页扫描PDF——这些看似简单的图像&#xff0c;背后却隐藏着大量需要结构化录入的信息。传统OCR工具要…

作者头像 李华
网站建设 2026/5/9 4:31:03

LoRA强度调节技巧:ora:my_style_lora:0.8参数含义与最佳实践

LoRA强度调节的艺术&#xff1a;从ora:my_style_lora:0.8看微调控制的精细之道 在如今AIGC创作愈发普及的背景下&#xff0c;越来越多设计师、内容创作者甚至企业开始尝试用AI生成专属视觉风格。但一个常见困扰是&#xff1a;训练好的LoRA模型&#xff0c;为什么有时“太猛”导…

作者头像 李华
网站建设 2026/5/10 9:44:03

手把手教你启动‘1-界面推理-pt.sh’脚本并访问Web页面

手把手教你启动 1-界面推理-pt.sh 脚本并访问 Web 页面 在企业数字化转型加速的今天&#xff0c;如何快速、安全地将纸质文档转化为结构化数据&#xff0c;已成为财务、政务、教育等领域的共性需求。传统 OCR 工具要么精度不足&#xff0c;要么部署复杂&#xff0c;往往需要专业…

作者头像 李华