二叉搜索树/二叉排序树/二叉查找树
什么是二叉搜索树
二叉搜索树(BST,Binary Search Tree), 也称二叉排序树或二叉查找树 。一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值(/关键字)。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
- 注意:二叉排序树中没有相同关键字的结点。对二叉搜索树进行中序遍历可以得到按关键字排序的有序序列。*
//在讨论二叉排序树上的运算之前,定义其节点的类型如下:
typedef int keyType
typedef struct node //记录类型
{ KeyType key; //关键字项
InfoType data; //其他数据域
struct node *lchild,*rchild; //左右孩子指针
}
BSTNode;
二叉搜索树的指定结点的查找
顾名思义,这种二叉树就是用来查找的。
因为二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。
查找从根结点开始,如果树为空,返回NULL 。
若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:
若X小于根结点键值,只需在左子树中继续搜索;如果X大于根结点的键值,在右子树中进行继续搜索; 若两者比较结果是相等,搜索完成,返回指向此结点的指针。
//递归
BSTNode *SearchBST(BSTNode *bt,KeyType k)
{ if(bt==NULL || bt->key==k) //递归终结条件
return bt;
if (k<bt->key)
return SearchBST(bt->lchild,k); //在左子树中递归查找
else return SearchBST(bt->rchild,k); //在右子树中递归查找
}
由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数 :
//非递归
BSTNode *SearchBST1(BSTNode *bt,KeyType k)
{
while (bt!=NULL)
{if (k==bt->key)return bt;
else if (k<bt->key)bt=bt->lchild; //在左子树中递归查找
elsebt=bt->rchild; //在左子树中递归查找
}
return NULL; //没有找到返回NULL
}
注:查找的效率决定于树的高度
查找最大和最小元素
按照性质,最大元素一定是在树的最右分枝的端结点上 ;最小元素一定是在树的最左分枝的端结点上 。参考代码如下,按英文意思进行理解即可:
//查找最小元素的递归函数
Position FindMin( BinTree BST )
{
if( !BST )
return NULL; /*空的二叉搜索树,返回NULL*/
else if( !BST->Left ) return BST; /*找到最左叶结点并返回*/
else return FindMin( BST->Left ); /*沿左分支继续查找*/ } //查找最大元素的迭代函数
Position FindMax( BinTree BST )
{
if(BST)
while( BST->Right )
BST = BST->Right; /*沿右分支继续查找,直到最右叶结点*/
return BST;
}
二叉搜索树的插入
关键是要找到元素应该插入的位置。
插入过程:
(1)若二叉排序树T为空,则创建一个key域为k的节点,将它作为根节点;
(2)否则将k和根节点的关键字比较,若两者相等,则说明树中已有此关键字k,无须插入,直接返回0;
(3)若kkey,则将k插入根节点的左子树中。
(4)否则将它插入右子树
int InsertBST(BSTNode *&p,KeyType k) //在以*p为根节点的BST中插入一个关键字为k的节点。插入成功返回1,否则返回0
{
if(p==NULL) //原树为空, 新插入的记录为根节点
{
p=(BSTNode*)malloc(sizeof(BSTNode));
p->key=k;
p->lchild=p->rchild=NULL;
return 1;
}
else if (k==p->key) //存在相同关键字的节点,返回0
return 0;
else if (k<p->key) return InsertBST(p->lchild,k); //插入到左子树中
else return InsertBST(p->rchild,k); //插入到右子树中}
二叉搜索树的生成
二叉排序树的生成,是从一个空树开始,每插入一个关键字,就调用一次插入算法将它插入到当前已生成的二叉排序树中。
BSTNode *CreatBST(KeyType A[],int n) //返回树根指针
{
BSTNode *bt=NULL; //初始时bt为空树
int i=0;
while (i<n)
{
InsertBST(bt,A[i]); //将A[i]插入二叉排序树T中
i++;
}
return bt; //返回建立的二叉排序树的根指针}
任何节点插入到二叉排序树时,都是以叶子节点插入的。
**二叉搜索树的删除 **
这个过程是最复杂的。
1.①被删除的节点是叶子节点:直接删去该节点。其双亲节点中相应指针域的值改为“空”
②被删除的节点只有左子树或者只有右子树,用其左子树或者右子树代替它。其双亲节点的相应指针域的值改为 “指向被删除节点的左子树或右子树”。
③被删除的节点既有左子树,也有右子树:以其前驱替代之,然后再删除该前驱节点。前驱是左子树中最大的节点
int DeleteBST(BSTNode *&bt,KeyType k) //在bt中删除关键字为k的节点
{
if(bt==NULL) return 0; //空树删除失败
else
{if (k<bt->key)
return DeleteBST(bt->lchild,k);//递归在左子树中删除为k的节点
else if (k>bt->key) return DeleteBST(bt->rchild,k);//递归在右子树中删除为k的节点
else
{
Delete(bt); //调用Delete(bt)函数删除*bt节点
return 1;
}
}}void Delete(BSTNode *&p) //从二叉排序树中删除*p节点
{
BSTNode *q;
if(p->rchild==NULL) //*p节点没有右子树的情况
{
q=p;
p=p->lchild; //其左子树的根节点放在被删节点的位置上
free(q);
}
else if (p->lchild==NULL) //*p节点没有左子树
{
q=p;
p=p->rchild; //其右子树的根节点放在被删节点的位置
free(q);
}
else Delete1(p,p->lchild); //*p节点既有左子树又有右子树的情况
}void Delete1(BSTNode *p,BSTNode *&r) //当被删*p节点有左右子树时的删除过程
{
BSTNode *q;
if (r->rchild!=NULL) Delete1(p,r->rchild); //递归找最右下节点
else //找到了最右下节点*r
{
p->key=r->key; //将*r的关键字值赋给*p
q=r;
r=r->lchild; //将左子树的根节点放在被删节点的位置上
free(q); //释放原*r的空间
}}
2.另一种类似做法:
考虑三种情况:
①要删除的是叶结点:直接删除,并再修改其父结点指针—置为NULL ;
②要删除的结点只有一个孩子结点: 将其父结点的指针指向要删除结点的孩子结点 ;
③要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素 ;取右子树中的最小元素替代 ,取左子树中的最大元素替代 ;
BinTree Delete( ElementType X, BinTree BST )
{
Position Tmp;
if( !BST )
printf("要删除的元素未找到");
else if( X < BST->Data )
BST->Left = Delete( X, BST->Left); /* 左子树递归删除 */
else if( X > BST->Data )
BST->Right = Delete( X, BST->Right); /* 右子树递归删除 */
else /*找到要删除的结点 */
if( BST->Left && BST->Right )
{ /*被删除结点有左右两个子结点 */
Tmp = FindMin( BST->Right ); /*在右子树中找最小的元素填充删除结点*/
BST->Data = Tmp->Data;
BST->Right = Delete( BST->Data, BST->Right); /*在删除结点的右子树中删除最小元素*/
}
else { /*被删除结点有一个或无子结点*/
Tmp = BST;
if( !BST->Left ) /* 有右孩子或无子结点*/
BST = BST->Right;
else if( !BST->Right ) /*有左孩子或无子结点*/
BST = BST->Left;
free( Tmp );
}
return BST;
}
二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下.那么如何提高效率,即如何避免磁盘过于频繁的多次查找呢?根据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度。这样的树就是:平衡二叉树
各种树
平衡二叉树
B-和B+树的定义、性质特点、举例说明
线索二叉树
哈夫曼树Huffman Tree
二叉搜索树/二叉排序树/二叉查找树相关推荐
- 详解二叉排序树(二叉搜索树、二叉查找树)以及Python实现相关操作
二叉排序树 引言 1.定义 2.性质 3.操作 3.1 查找 3.2 插入 3.3 生成 3.4 删除 引言 如何更加高效的完成对数据的查询和添加操作,例如↓↓↓ 给你一个数列 (7, 3, 10, ...
- 二叉排序树(二叉搜索树,二叉查找树)
递归实现二叉搜索树(BST)的创建 以数组的形式实现(循环) 以递归的形式实现
- Binary Search Tree(二叉搜索树、二叉查找树、二叉排序树)
搜索树数据结构支持许多动态几何操作,包括SEARCH.MININUM.MAXINUM.PREDECESSOR.SUCCESSOR.INSERT和DELETE等.因此,我们可以使用一个搜索树作为字典或者 ...
- 二叉搜索树 java_二叉查找树之 Java的实现【下】
/** * Java 语言: 二叉查找树 * * @author skywang * @date 2013/11/07 */ public class BSTree>{ private BSTN ...
- 递归1:二叉搜索树的范围和
给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和. 二叉搜索树保证具有唯一的值. 示例 1: 输入:root = [10,5,15,3,7,null,18], L = 7 ...
- 数据结构与算法之二叉搜索树
与链表不同,树是一种非线性的数据结构.树中最常用的是二叉树,二叉树限制了子树的数量,也就是每个结点的子树至多2个,并且这两个子树是有顺序的.而二叉搜索树(二叉查找树,二叉排序树)是指根节点的关键字大于 ...
- leetcode - 96. 不同的二叉搜索树
96. 不同的二叉搜索树 ------------------------------------------ 给定一个整数 n,求以 1 - n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 ...
- 二叉搜索树的2层结点统计_植树节,程序猿种的那些树
公历 3 月 12 日是一年一度的植树节.旨在宣传保护森林,并动员群众参加植树造林活动.说到树,程序猿们肯定不陌生,趁着这个植树节到来之时普及一下程序猿们经常遇见的树. 1. 二叉搜索树 定义 二叉搜 ...
- 二叉搜索树,二叉平衡术,红黑树,B树,B+树
二叉搜索树 二叉搜索树 平衡二叉树 红黑树 B树 B+树 二叉搜索树 二叉排序树定义: 二叉排序树或者是空树或者是满足以下条件: 1)若它的左子树不空,则左子树上的所有关键字小于根关键字的值 2)若它 ...
最新文章
- .Net Core MVC初学习
- 从CV到ML 直播场景下新技术的应用
- 写聊天室之前 了解聊天室拓展出来的各种知识点
- Android平台监听系统截屏方案预研及相关知识点
- xib 设置阴影_使用“IBInspectable”XIB设置圆角、边框、阴影
- 你绝对想不到R文件找不到(cannot resolve symbol R)的原因
- Log4j的组件和配置文件介绍
- SAP Hybris Commerce里的数据库表
- 巨一自动化工业机器人_2021第11届深圳国际工业自动化及机器人展览会
- alchemy php,Flask SQLAlchemy
- 生产上完成TopN统计流程
- apache httpd mysql_Centos7安装配置Apache(httpd)+php+mysql+phpMyAdmin
- java将图片上传数据库_〔技巧实例〕轻松实现将上传图片到数据库
- 高并发网络编程之epoll(个人遇到最好理解的一篇文章、易懂)
- 特斯拉又烧一辆!车库里起火 所幸无人受伤
- python工具包: pandas
- 【原生JS】web原生文字轮播效果
- matlab动力学系统仿真 教程,MATLAB/SIMULINK动力学系统建模与仿真
- 【语言-c#】应用程序正常初始化(0xc000007b)失败。请单击“确定”,终止应用程序。
- 《爱的五种能力》阅读笔记(完整版)
热门文章
- 五种常用设计模式的python实现:单例、工厂、构建者、代理、观察模式
- hadoop作业全流程图解
- 臀大肌(06):跪撑举臂抬腿
- java poi 图片 内存溢出_解决java poi海量数据导出内存溢出问题
- 基于mips内核的Atheros芯片--wlan中的VAP的创建
- FPGA基础知识 2(Xilinx/Altera FPGA 中的逻辑资源--Slices VS LE 比较)
- k8s 使用 calico 作为 CNI ,calico-node 启动失败
- Oracle数据类型转换
- oracle浮点型数据类型,ORACLE的数据类型float(b)
- 西南交通大学计算机相关专业考研科目及概述