二叉排序树的查找、插入、创建和删除
二叉排序树的特性:
1、若左子树非空,则左子树上所有结点的值均小于根节点的值;
2、若右子树非空,则右子树上所有结点的值均大于根节点的值;
3、左右子树又分别是一颗二叉排序树;
综上,左子树结点的值<根结点的值<右子树结点的值。所以对二叉排序树进行中序遍历,可以得到一个递增的有序序列。
1、数据结构定义
typedef struct BSTNode{int key;struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
2、二叉树的查找非递归
二叉树的查找是从根结点开始,逐层向下比较,若二叉排序树非空,关键字与根结点的值相比较,若相等,则查找成功,若大于,往右子树寻找,若小于,往左子树寻找。
//二叉排序树的非递归查找
BSTNode *BST_Search(BSTree T,int key)
{while(T!=NULL&&T.key!=key) //树不空以及没找到关键字 {if(T.key<key) //根结点小于关键字,左子树寻找 {T=T->lchild;} else //否则右子树寻找 {T=T->rchild;} }return T;}
非递归算法的空间复杂度是O(1)。
3、二叉排序树的递归查找
//二叉排序树的递归查找
BSTNode *BST_Search(BSTree T,int key)
{if(T==NULL) //查找失败 return T;if(T.key==key) //查找成功 {return T;}else if(T.key>key)return BST_Search(T->lchild,key);elsereturn BST_Search(T->rchild,key);}
但是递归查找,由于需要一个递归工作栈,所以其空间复杂度是树高,最坏情况就是一棵单子树,即时间复杂度为O(n)。
4、 二叉排序树的递归插入
由于二叉排序树中不存在两个值相等的结点,所以当插入时,发现插入的值与树中某个结点的值相等,则插入失败。
插入过程:
1、若二叉树为空,则直接插入结点;
2、否则,若关键字小于根结点的值,则插入到左子树中,若关键字大于根结点的值,则插入到右子树中。插入的结点一定是一个新添加的叶结点,且是查找失败时的查找路径上访问的最后一个结点的左孩子或右孩子。
//二叉排序树的插入(递归实现)
int BST_Insert(BSTree &T,int k)
{if(T==NULL){T=(BSTree)malloc(sizeof(BSTNode));T->key=k;T->lchild=T->rchild=NULL;return 1; //插入成功 }else if(T->key==k) //有重复值,插入失败 return 0;else if(T->key<key)return BST_Insert(T->rchild,k);elsereturn BST_Insert(T->lchild,k);}
其时间复杂度为:O(h),h是树高。
5、 二叉排序树的创建
二叉树的创建过程,其实就是一个不断插入的过程。
//二叉树的创建
void Creat_BST(BSTree &T,int a[],int n)
{T=NULL; //初始时T为空int i=0;while(i<n){BST_Insert(T,a[i]);i++;} }
不同的关键字序列可能得到同款二叉排序树,也可能得到不同的额二叉排序树。
6、二叉排序树的删除
二叉排序树的删除过程:
1、若被删除的结点是叶子结点,则直接删除;
2、若被删除的结点a只有一颗左子树或者右子树,则让 a的子树占领a的位置,成为a的父节点的子树。
3、若结点a有左右子树,则让a的直接后继(直接前驱也一样)替代a,然后从二叉排序树中删除这个直接后继(直接前驱),接着就转换为1或2的情况处理。
a的直接后继:a的右子树中最左下的结点,该结点一定没有左子树,且该结点的值是右子树中最小的。
a的直接前驱:a的左子树中最右下的结点,该结点一定没有右子树,且该结点的值是左子树中最大的。
对于第三种情况使用的是直接后继结点替补的:
//二叉排序树的删除
int BST_Delete(BSTree &T,int key)
{BSTree p=T;BSTree pre=NULL; //指向要删除结点的前一个结点 while(p!=NULL&&p->key!=key) //先找到要删除的结点 {if(key>p->key){pre=p;p=p->rchild;}else{pre=p;p=p->lchild;}} if(p==NULL) //要删除的结点不存在 return 0; else{//第一种情况:删除叶子结点,直接删if(p->lchild==NULL&&p->rchild==NULL){if(pre->key<key){pre->rchild=NULL;} else{pre->lchild=NULL;}} //第二种情况:单子树 else if((p->lchild==NULL&&p->rchild)||(p->rchild==NULL&&p->lchild)){if(pre->key<key){if(p->rchild) //右子树存在 {pre->rchild=p->rchild;}else //左子树存在 {pre->rchild=p->lchild;}}else{if(p->rchild){pre->lchild=p->rchild;} else{pre->lchild=p->lchild;}}} //第三种情况:左右子树都存在,这里我使用的是用直接后继填补(直接前驱一样,后面也给出)else if(p->lchild&&p->rchild){BSTree *pre1=p; //由于要删除的结点不需要动,只是被替换,所以不需要知道被删除结点的前驱,而是要知道被替换结点的前驱BSTree *q=p->rchild;while(q->lchild) //寻找右子树的最左下的结点 {pre1=q;q=q->lchild;} p->key=q->key; //替换结点值 if(p!=pre1) //右子树的左子树存在 {pre1->lchild=q->lchild; }else //右子树的左子树不存在,用根替换的 {pre1->rchild=q->rchild;}delete(q);} return 1; //删除成功 }
}
对于第三种情况使用的是直接前驱结点替补的:
//二叉排序树的删除
int BST_Delete(BSTree &T,int key)
{BSTree p=T;BSTree pre=NULL; //指向要删除结点的前一个结点 while(p!=NULL&&p->key!=key) //先找到要删除的结点 {if(key>p->key){pre=p;p=p->rchild;}else{pre=p;p=p->lchild;}} if(p==NULL) //要删除的结点不存在 return 0; else{//第一种情况:删除叶子结点,直接删if(p->lchild==NULL&&p->rchild==NULL){if(pre->key<key){pre->rchild=NULL;} else{pre->lchild=NULL;}} //第二种情况:单子树 else if((p->lchild==NULL&&p->rchild)||(p->rchild==NULL&&p->lchild)){if(pre->key<key){if(p->rchild) //右子树存在 {pre->rchild=p->rchild;}else //左子树存在 {pre->rchild=p->lchild;}}else{if(p->rchild){pre->lchild=p->rchild;} else{pre->lchild=p->lchild;}}} //第三种情况:左右子树都存在,这里我使用的是用直接后继填补(直接前驱一样,后面也给出)else if(p->lchild&&p->rchild){BSTree *pre1=p; //由于要删除的结点不需要动,只是被替换,所以不需要知道被删除结点的前驱,而是要知道被替换结点的前驱BSTree *q=p->lchild;while(q->rchild) //寻找左子树的最右下的结点 {pre1=q;q=q->rchild;} p->key=q->key; //替换结点值 if(p!=pre1) //左子树的右子树存在 {pre1->rchild=q->lchild; }else //左子树的右子树不存在,用根替换的 {pre1->lchild=q->lchild;}delete(q);} return 1; //删除成功 }
}
二叉排序树的查找、插入、创建和删除相关推荐
- 【Python数据结构】——二叉查找树(查找、构建、删除、插入、打印)
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/7/15 0:34 # @Author : @linlianqin # @Si ...
- 数据结构(8-3)二叉排序树(查找、插入删除)
目录 一.基础理论 1.特点: 2.结构: 二.查找 三.插入 四.删除 1.被删除的结点D是叶子结点 2.被删除的结点D仅有一个孩子 2-1.删除结点14(有左无右) 2-2.删除结点 10 (有右 ...
- 重温数据结构:二叉排序树的查找、插入、删除
读完本文你将了解到: 什么是二叉排序树 Binary Sort Tree, BST 二叉排序树的关键操作 1.查找 2.插入 3.删除 * 运行代码测试 一道面试题 总结 Thanks 我们知道,二分 ...
- 二叉树排序树插入、创建、删除和查找
二叉树排序树插入.创建.删除和查找 二叉排序树的概念 二叉排序树又称二叉查找树,它或者是一棵空树,或者是具有下列性质的二叉树 若它的左子树不为空,则左子树上所有结点的值均小于根结点的值 若它的右子 ...
- 【大话数据结构C语言】56 二叉排序树的查找、插入和删除
欢迎关注我的公众号是[CodeAllen],关注回复[1024]获取精品学习资源 程序员技术交流①群:736386324 ,程序员技术交流②群:371394777 目录 二叉排序树查找关键字 二叉排序 ...
- Python使用SQLAlchemy连接数据库并创建数据表、插入数据、删除数据、更新表、查询表(CRUD)
Python使用SQLAlchemy连接数据库并创建数据表.插入数据.删除数据.更新表.查询表(CRUD) 目录 Python使用SQLAlchemy连接数据库并创建数据表 #SQLAlchemy # ...
- mybatis存在就不插入_mybatis只能进行查找,不能进行删除,插入,更新解决方案...
mybatis只能进行查找,不能进行删除,插入,更新 mybatis只能进行查找,不能进行删除,插入,更新 ,是不是哪里配置错了? 求各位大神!!~~~ mybatis.xml XML code< ...
- 单链表的创建、删除、反转、插入、排序操作
单链表的创建.删除.反转.插入.排序操作 文章目录 单链表的创建.删除.反转.插入.排序操作 1.1 链表引言 1.2 单链表节点的数据结构 1.3 创建链表 1.4 打印整个链表 1.5 链表插入数 ...
- jquery 元素节点操作 - 创建节点、插入节点、删除节点
jquery的节点操作说明 前面的篇章对于jquery的元素操作大部分是使用html()的方式来操作,这种直接使用字符串创建的方式也是性能最高的. 使用html()操作节点 首先编写一个div包含一个 ...
最新文章
- 醉没醉,带上智能手机走两步就知道
- P5319-[BJOI2019]奥术神杖【0/1分数规划,AC自动机,dp】
- macOS Big Sur怎么样?值得升级吗?Big Sur与Catalina的对比
- java连接mysql数据库时出现乱码_java连接mysql数据库中文乱码问题
- 【Luogu1095】守望者的逃离
- Vue之安装Google开发插件
- Java设计模式——建造者模式
- 容器技术Docker K8s 24 容器服务ACK基础与进阶-日志管理
- 源码分享—《Java多线程编程核心技术》源码,Java多线程编程核心技术源码 略微有改动。
- java后台怎么解密md5,Java md5 密码加解密
- 年终了,大家要小心!
- 第七章、TPP2(G2)
- 数据仓库ETL工具箱——实时ETL系统
- Android端WebRTC本地音视频采集流程源码分析
- 社会工程学攻击之网站钓鱼
- 详细讲解如何映射网络驱动器
- 从0开发一个Dapp
- 使用springboot每日推送早安问候语到用户微信【部署篇】
- 电竞游戏而生,这款高清显示器要逆天了~
- 基于Windows Embedded部署物流配货系统加快物流速度
热门文章
- matlab等式操作,matlab处理一个等式方程,急用,谢谢
- 大四 Java开发实习近一年 记录(每6至12月更新一次)
- mmsegmentation安装过程报错记录
- 电子天平的检定和检定结果的影响因素
- 概率统计笔记:共轭分布
- 生产物流系统建模与仿真-基于WITNESS建模视频教程
- 中国移动明确5G商用时间表
- linux镜像文件太大不好下载_这是什么神仙系统?支持安卓程序 + Windows 程序 + Linux 程序...
- [Android 之美] 那些你不知道的APK 瘦身,让你的APK更小
- 浙大OJ网址及ACM题目分类