二叉排序树(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

相关文章

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

Macos创建python虚拟环境的详细步骤教学

《Macos创建python虚拟环境的详细步骤教学》在macOS上创建Python虚拟环境主要通过Python内置的venv模块实现,也可使用第三方工具如virtualenv,下面小编来和大家简单聊聊... 目录一、使用 python 内置 venv 模块(推荐)二、使用 virtualenv(兼容旧版 P

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

使用C#删除Excel表格中的重复行数据的代码详解

《使用C#删除Excel表格中的重复行数据的代码详解》重复行是指在Excel表格中完全相同的多行数据,删除这些重复行至关重要,因为它们不仅会干扰数据分析,还可能导致错误的决策和结论,所以本文给大家介绍... 目录简介使用工具C# 删除Excel工作表中的重复行语法工作原理实现代码C# 删除指定Excel单元

Linux lvm实例之如何创建一个专用于MySQL数据存储的LVM卷组

《Linuxlvm实例之如何创建一个专用于MySQL数据存储的LVM卷组》:本文主要介绍使用Linux创建一个专用于MySQL数据存储的LVM卷组的实例,具有很好的参考价值,希望对大家有所帮助,... 目录在Centos 7上创建卷China编程组并配置mysql数据目录1. 检查现有磁盘2. 创建物理卷3. 创

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、