当前位置: 首页 > news >正文

数据结构——四十二、二叉排序树(王道408)

文章目录

  • 前言
  • 一.二叉排序树的定义
  • 二.二叉排序树的查找
    • 1.思路
    • 2.代码
    • 3.使用过程
  • 三.二叉排序树的插入
    • 1.思路
    • 2.代码
    • 3.使用过程
  • 四.二叉排序树的构造
    • 1.思路
    • 2.代码
    • 3.使用过程
  • 五.二叉排序树的删除
    • 1.思路
  • 六.查找效率分析
    • 1.查找成功
      • 1.计算平均查找长度(ASL)
      • 2.查找的时间复杂度
    • 2.查找失败
      • 1.计算平均查找长度(ASL)
  • 七.知识回顾与重要考点
  • 结语

前言

本文介绍了二叉排序树(BST)的定义、查找、插入、构造和删除操作。二叉排序树是一种左子树结点值小于根结点值,右子树结点值大于根结点值的特殊二叉树,其中序遍历可得到递增序列。查找操作通过比较关键字值在左右子树中递归搜索。插入操作根据关键字大小决定插入位置。构造BST即不断插入新结点的过程。删除操作需分三种情况处理:删除叶子结点、仅有一棵子树的结点或两棵子树的结点。对于同时有左右子树的结点,可采用直接后继代替法处理。文章通过图示和代码示例详细说明了各操作的实现过程和应用场景。

一.二叉排序树的定义

在这里插入图片描述

  • 二叉排序树,又称二叉查找树(BST). Binary Search Tree)
  • 一棵二叉树或者是空二叉树,或者是具有如下性质的二叉树:
    左子树上所有结点的关键字均小于根结点的关键字;
    右子树上所有结点的关键字均大于根结点的关键字。
    左子树和右子树又各是一棵二叉排序树。

左子树结点值 < 根结点值 < 右子树结点值
进行中序遍历,可以得到一个递增的有序序列

二叉排序树可用于元素的有序组织、搜索

二.二叉排序树的查找

1.思路

  • 若树非空,目标值与根结点的值比较:
  • 若相等,则查找成功;
  • 若小于根结点,则在左子树上查找,否则在右子树上查找。
  • 查找成功,返回结点指针;查找失败返回NULL

2.代码

//二叉排序树结点
typedef struct BSTNode{int key;struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;//在二叉排序树中查找值为 key 的结点
BSTNode *BST_Search(BSTree T,int key){while(T!=NULL&&key!=T->key){//若树空或等于根结点值,则结束循环if(key<T->key) T=T->lchild;//小于,则在左子树上查找else T=T->rchild;//大于,则在右子树上查找}return T;
}//在二叉排序树中查找值为 key 的结点(递归实现)
BSTNode *BSTSearch(BSTree T,int key){if (T==NULL)return NULL;//查找失败if (key==T->key)return T;//查找成功else if (key<T->key)return BSTSearch(T->lchild, key); //在左子树中找elsereturn BSTSearch(T->rchild, key); //在右子树中找
}
  • 循环迭代算法空间复杂度:O(1)
  • 递归空间复杂度:O(h),h为树的高度

3.使用过程

在这里插入图片描述

  • 查找关键字为30的结点
  1. 从根节点出发,如果当前访问的节点是一个非空节点,并且我们要找到那个值是要大于当前节点的,那么根据排序数的特性,我们要找的点肯定是在右子树中,所以我们可以让指针往他的右孩子方向走
    在这里插入图片描述
  2. 现在我们要查找的节点30要比50更小,那肯定是在50这个节点的左子树上,所以就可以往左走
    在这里插入图片描述
  3. 接下来的操作类似,结果如下:
    在这里插入图片描述
  4. 假设此时T指向的是NULL,说明查找失败

三.二叉排序树的插入

1.思路

  • 若原二叉排序树为空,则直接插入结点;否则,若关键字k小于根结点值,则插入到左子树,若关键字k大于根结点值,则插入到右子树

2.代码

//在二叉排序树插入关键字为k的新结点(递归实现)
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;	//返回1,插入成功}else if(k==T->key)	//树中存在相同关键字的结点,插入失败return 0;else if(k<T->key)	//插入到T的左子树return BST_INSERT(T->lchild,k);else	//插入到T的右子树return BST_INSERT(T->rchild,k);
}// 非递归插入新结点到二叉排序树
bool InsertBST(BSTree *T, int key) {// 创建新结点BSTNode *newNode = (BSTNode *)malloc(sizeof(BSTNode));if (newNode == NULL) {return false; // 内存分配失败}newNode->key = key;newNode->lchild = newNode->rchild = NULL;// 如果树为空,新结点作为根结点if (*T == NULL) {*T = newNode;return true;}BSTNode *current = *T;BSTNode *parent = NULL;// 寻找插入位置while (current != NULL) {parent = current;if (key == current->key) {free(newNode); // 键值已存在,释放新结点return false;  // 插入失败} else if (key < current->key) {current = current->lchild; // 在左子树中查找} else {current = current->rchild; // 在右子树中查找}}// 插入新结点if (key < parent->key) {parent->lchild = newNode;} else {parent->rchild = newNode;}return true;
}
  • 递归方式最坏空间复杂度O(h),h为树的高度
  • 非递归方式空间复杂度为O(1)

3.使用过程

在这里插入图片描述

  • 插入关键字为12的结点
  1. 那么从根节点出发,12比19更小,那显然应该插入到左子树
    在这里插入图片描述
  2. 接下来12小于13,所以还应该插入到它的左子树当中
    在这里插入图片描述
  3. 那现在12大于11,所以应该插入到当前节点的右子树当中
    在这里插入图片描述
  4. 如果二叉树中已经有关键字为12的元素,则插入失败

新插入的结点一定是叶子节点

四.二叉排序树的构造

1.思路

  • 就是不断插入新结点的过程

2.代码

//按照 str[]中的关键字序列建立二叉排序树
void Creat_BST(BST&T, int str[], int n){T=NULL;	//初始时T为空树int i=0;while(i<n){//依次将每个关键字插入到二叉排序树中BST Insert(T,str[i]);i++;}
}

3.使用过程

  • 例1: 按照序列str={50,66,60,26,21,30,70,68}建立BST
  1. 首先插入的是50
    在这里插入图片描述
  2. 接下来66>50,插入到右孩子
    在这里插入图片描述
  3. 60<60应该插在66的左边
    在这里插入图片描述
  4. 然后是26<50,插在50的左孩子
    在这里插入图片描述
  5. 接下来操作一样,最终结果如下:
    在这里插入图片描述
  • 例2:按照序列str={50,26,21,30,66,60,70,68}建立BST
  • 也是一样的,这里就不展示过程了,直接看结果

在这里插入图片描述

不同的关键字序列可能得到同款二叉排序树

五.二叉排序树的删除

1.思路

  • 先搜索找到目标结点:
    ①若被删除结点z是叶结点,则直接删除,不会破坏二叉排序树的性质。
    在这里插入图片描述
    在这里插入图片描述
    ②若结点z只有一棵左子树或右子树,则让z的子树成为z父结点的子树,替代z的位置。
    在这里插入图片描述
    在这里插入图片描述
    ③若结点z有左、右两棵子树,
    1. 第一种方案(直接后继代替法)我们可以从当前删除的节点,它的右子树当中找到值最小的节点(右子树中中序遍历的第一个结点,在树上面看就时左子树中最左下的那个节点),用那个节点来替代当前被删除的节点
    2. 由于p所指向的结点一定是最左下的结点,因此其一定没有左子树,这样就转换成了我们之前的第二/一种情况
      在这里插入图片描述
      在这里插入图片描述
    3. 第二种方案(直接前驱替代法),找到当前节点它的左子树当中最大的那个值(左子树中最右下的结点),用左子树当中最大的值来替代当前被删除的节点.和之前类似的,p所指向的结点一定没有右子树,则可以转换为之前的第一/二种情况
      在这里插入图片描述

六.查找效率分析

1.查找成功

1.计算平均查找长度(ASL)

在这里插入图片描述

  • ASL=(1∗1+2∗2+3∗4+4∗1)/8=2.625ASL=(1*1+2*2+3*4+4*1)/8=2.625ASL=(11+22+34+41)/8=2.625
    在这里插入图片描述
  • ASL=(1∗1+2∗2+3∗1+4∗1+5∗1+6∗1+7∗1)/8=3.75ASL = (1*1 + 2*2 + 3*1 + 4*1 + 5*1 + 6*1+ 7*1)/8 = 3.75ASL=(11+22+31+41+51+61+71)/8=3.75

2.查找的时间复杂度

  • 最好情况:n个结点的二叉树最小高度为⌊log⁡2n⌋+1\lfloor\log_{2}n\rfloor+1log2n+1。平均查找长度=O(log2n)O(log_{2}n)O(log2n)
  • 最坏情况:每个结点只有一个分支,树高h=结点数n。平均查找长度=O(n)

2.查找失败

1.计算平均查找长度(ASL)

在这里插入图片描述

  • ASL=(3∗7+4∗2)/9=3.22ASL=(3*7+4*2)/9=3.22ASL=(37+42)/9=3.22

在这里插入图片描述

  • ASL=(2∗3+3+4+5+6+7∗2)/9=4.22ASL=(2*3+3+4+5+6+7*2)/9=4.22ASL=(23+3+4+5+6+72)/9=4.22

七.知识回顾与重要考点

在这里插入图片描述

结语

二更😉

如果想查看更多章节,请点击:一、数据结构专栏导航页

http://www.dtcms.com/a/605276.html

相关文章:

  • VueUse的使用
  • 【LeetCode】111. 二叉树的最小深度
  • 如何将html发布到网站wordpress用户筛选
  • 深度智能体-智能体加强版
  • ZCC75XXH- 40V/150mA 高压线性稳压器替代HT75XX
  • 多媒体语音通话中,信令参数T1/ms, T2/s, T4/s作用
  • Travel uni-app 项目说明
  • 永磁同步电机无速度算法--基于一阶线性状态观测器的反电动势观测器
  • 番禺网站建设怎样网站建设公司怎样做账
  • 网站开发项目总结模板网站开发 证书
  • Python 自定义迭代器 --以斐波那契数列为例
  • AI一键PPT 2.0.3 一键智能生成
  • 232. 用栈实现队列
  • 如何在桌面创建网页快捷图标?(电脑 / 手机通用操作指南)
  • soular实战教程系列(2) - 如何统一管理TikLab帐号体系
  • k8s 发行说明(版本)
  • 批处理病毒原理、防御
  • 网站建设对企业的好处有哪些嘉兴网站制作建设
  • 几大网站类型网站建设所需人员
  • KAFKA自动修改所有以**开头的主题脚本
  • 记录生活系统|记录美好|健康管理|基于java+Android+微信小程序的记录生活系统设计与实现(源码+数据库+文档)
  • PHP Calendar
  • 用 Kafka 打通实时数据总线Flink CDC Pipeline 的 Kafka Sink 实战
  • Podman讲解
  • PHP EOF (Heredoc)
  • Spring Boot集成Kafka:最佳实践与详细指南
  • 【运维】Docker 入门
  • 手机网站的尺寸做多大的如何搭建wordpress商城
  • 百度商桥绑定网站正规的关键词优化软件
  • F280049C学习笔记之CMPSS