二叉排序树(BST)的创建,查找,插入,删除及最大最小结点

2024-05-02 18:58

本文主要是介绍二叉排序树(BST)的创建,查找,插入,删除及最大最小结点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考:https://blog.csdn.net/happyjacob/article/details/82795560

1、什么是二叉排序树

二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树

二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

  1. 非空左子树的所有键值小于其根结点的键值。
  2. 非空右子树的所有键值大于其根结点的键值。
  3. 左、右子树都是二叉搜索树。

2、二叉搜索树的查找操作

  • 查找从根结点开始,如果树为空,返回NULL

  • 若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:

    1. 若X小于根结点键值,只需在左子树中继续搜索;
    2. 如果X大于根结点的键值,在右子树中进行继续搜索;
    3. 若两者比较结果是相等,搜索完成,返回指向此结点的指针。

å¨è¿éæå¥å¾çæè¿°

递归实现

//查找,递归实现
BTNode * SearchBST(BTree pT, ElemType key) {if (pT == nullptr)return nullptr;if (key > pT->val) {SearchBST(pT->right, key);}else if(key < pT->val){SearchBST(pT->left, key);}else {return pT;}
}

由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数

非递归实现

//查找,非递归实现
BTNode * SearchBST(BTree pT, ElemType key) {while (pT != nullptr) {if (key < pT->val) {pT = pT->left;}else if (key > pT->val) {pT = pT->right;}else {return pT;}}return nullptr;
}

3、查找最大和最小元素

最大元素一定是在树的最右分枝的端结点上
最小元素一定是在树的最左分枝的端结点上

å¨è¿éæå¥å¾çæè¿°

//递归寻找最大值
BTNode * findMax(BTree pT) {if (pT == nullptr)return nullptr;else {if (pT->right != nullptr) {findMax(pT->right);}else {return pT;}}
}//非递归寻找最小值
BTNode * findMin(BTree pT) {if (pT == nullptr)return nullptr;while (pT->left != nullptr) {pT = pT->left;}return pT;
}

4、二叉搜索树的插入

关键是要找到元素应该插入的位置,可以采用与Find类似的方法

可以用二叉搜索树的插入来创建二叉搜索树

//二叉搜索树的插入
BTree Insert(BTree pT, ElemType key) {if (pT == nullptr) {BTNode *node = new BTNode(key);}else if (key < pT->val) {pT->left = Insert(pT->left, key);}else if (key > pT->val) {pT->right = Insert(pT->right, key);}else {//节点存在,什么都不做,或者打印信息cout << "节点已经存在" << endl;}return pT;
}

5、二叉搜索树的删除

考虑三种情况:

  1. 要删除的结点的左孩子为空:右孩子代替当前结点

å¨è¿éæå¥å¾çæè¿°

     2.要删除的结点的右孩子为空:左孩子代替当前结点

    3.要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素

å¨è¿éæå¥å¾çæè¿°

//二叉搜索树的删除
BTree Delete(ElemType x, BTree pT) {if (pT == nullptr) {return nullptr;}if (x > pT->val) {pT->right = Delete(x, pT->right);}else if (x < pT->val) {pT->left = Delete(x, pT->left);}else {if (pT->left && pT->right) {BTNode *tp = findMin(pT->right);pT->val = tp->val;pT->right = Delete(tp->val, pT->right);}else {if (pT->left == nullptr) {pT = pT->right;}else if (pT->right == nullptr) {pT = pT->left;}}	}return pT;
}

完整代码:

#include <iostream>
#include <vector>
#include <deque>using ElemType = int;using namespace std;typedef struct BTNode {ElemType val;struct BTNode *left, *right;BTNode(ElemType x) :val(x), left(nullptr), right(nullptr) {}
}BTNode, *BTree;//查找,递归实现
BTNode * SearchBST(BTree pT, ElemType key) {if (pT == nullptr)return nullptr;if (key > pT->val) {SearchBST(pT->right, key);}else if(key < pT->val){SearchBST(pT->left, key);}else {return pT;}
}//查找,非递归实现
BTNode * SearchBSTNonrecursion(BTree pT, ElemType key) {while (pT != nullptr) {if (key < pT->val) {pT = pT->left;}else if (key > pT->val) {pT = pT->right;}else {return pT;}}return nullptr;
}//查找最大和最小元素
//最大元素一定在树的最右分支的端节点上
//最小元素一定在树的最左分支的端节点上//递归寻找最大值
BTNode * findMax(BTree pT) {if (pT == nullptr)return nullptr;else {if (pT->right != nullptr) {findMax(pT->right);}else {return pT;}}
}//非递归寻找最小值
BTNode * findMin(BTree pT) {if (pT == nullptr)return nullptr;while (pT->left != nullptr) {pT = pT->left;}return pT;
}//二叉搜索树的插入
BTree Insert(BTree pT, ElemType key) {if (pT == nullptr) {pT = new BTNode(key);}else if (key < pT->val) {pT->left = Insert(pT->left, key);}else if (key > pT->val) {pT->right = Insert(pT->right, key);}else {//节点存在,什么都不做,或者打印信息cout << "节点已经存在" << endl;}return pT;
}//二叉搜索树的删除
BTree Delete(ElemType x, BTree pT) {if (pT == nullptr) {return nullptr;}if (x > pT->val) {pT->right = Delete(x, pT->right);}else if (x < pT->val) {pT->left = Delete(x, pT->left);}else {if (pT->left && pT->right) {BTNode *tp = findMin(pT->right);pT->val = tp->val;pT->right = Delete(tp->val, pT->right);}else {if (pT->left == nullptr) {pT = pT->right;}else if (pT->right == nullptr) {pT = pT->left;}}	}return pT;
}void preOrder(BTree pT) {//如果pT == nullptr,则什么也不做if (pT != nullptr) {//此处打印其值,也可以执行其他操作cout << pT->val;preOrder(pT->left);preOrder(pT->right);}
}int main() {//创建一棵平衡二叉树,将以下节点依次插入平衡二叉树vector<int> ivec = { 6, 2, 8, 1, 5, 3, 4 };BTree ptree = nullptr;for (auto i : ivec) {ptree = Insert(ptree, i);}//前序遍历遍历二叉树cout << "前序遍历二叉树:";preOrder(ptree);cout << endl;//删除一个节点,前序遍历ptree = Delete(2, ptree);cout << "删除节点2,再前序遍历:";preOrder(ptree);cout << endl;}

output:

前序遍历二叉树:6215348
删除节点2,再前序遍历:631548
请按任意键继续. . .

 

 

 

 

 

 

 

 

这篇关于二叉排序树(BST)的创建,查找,插入,删除及最大最小结点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954943

相关文章

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

idea+spring boot创建项目的搭建全过程

《idea+springboot创建项目的搭建全过程》SpringBoot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目,:本文主要介绍idea+springb... 目录一.idea四种搭建方式1.Javaidea命名规范2JavaWebTomcat的安装一.明确tomcat

Linux命令rm如何删除名字以“-”开头的文件

《Linux命令rm如何删除名字以“-”开头的文件》Linux中,命令的解析机制非常灵活,它会根据命令的开头字符来判断是否需要执行命令选项,对于文件操作命令(如rm、ls等),系统默认会将命令开头的某... 目录先搞懂:为啥“-”开头的文件删不掉?两种超简单的删除方法(小白也能学会)方法1:用“--”分隔命

C#自动化实现检测并删除PDF文件中的空白页面

《C#自动化实现检测并删除PDF文件中的空白页面》PDF文档在日常工作和生活中扮演着重要的角色,本文将深入探讨如何使用C#编程语言,结合强大的PDF处理库,自动化地检测并删除PDF文件中的空白页面,感... 目录理解PDF空白页的定义与挑战引入Spire.PDF for .NET库核心实现:检测并删除空白页

Python实现自动化删除Word文档超链接的实用技巧

《Python实现自动化删除Word文档超链接的实用技巧》在日常工作中,我们经常需要处理各种Word文档,本文将深入探讨如何利用Python,特别是借助一个功能强大的库,高效移除Word文档中的超链接... 目录为什么需要移除Word文档超链接准备工作:环境搭建与库安装核心实现:使用python移除超链接的

linux查找java项目日志查找报错信息方式

《linux查找java项目日志查找报错信息方式》日志查找定位步骤:进入项目,用tail-f实时跟踪日志,tail-n1000查看末尾1000行,grep搜索关键词或时间,vim内精准查找并高亮定位,... 目录日志查找定位在当前文件里找到报错消息总结日志查找定位1.cd 进入项目2.正常日志 和错误日

Git打标签从本地创建到远端推送的详细流程

《Git打标签从本地创建到远端推送的详细流程》在软件开发中,Git标签(Tag)是为发布版本、标记里程碑量身定制的“快照锚点”,它能永久记录项目历史中的关键节点,然而,仅创建本地标签往往不够,如何将其... 目录一、标签的两种“形态”二、本地创建与查看1. 打附注标http://www.chinasem.cn

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建