C++ 二叉搜索树

二叉搜索树的概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

·若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
·若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
·它的左右子树也分别为二叉搜索树

二叉搜索树的操作

二叉搜索树的查找

· 从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
· 最多查找高度次,走到到空,还没找到,这个值不存在。

二叉搜索树的插入

插入的具体过程如下:
· 树为空,则直接新增节点,赋值给root指针
· 树不空,按二叉搜索树性质查找插入位置,插入新节点

二叉搜索树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:

 ·  要删除的结点无孩子结点


 ·  要删除的结点只有左孩子结点


 ·  要删除的结点只有右孩子结点


 ·  要删除的结点有左、右孩子结点

看起来有待删除节点有4中情况,实际情况1可以与情况2或者3合并起来,因此真正的删除过程如下:

1:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
2:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
3:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除

二叉搜索树的实现

基本框架

我们需要实现二叉搜索树的插入,查找,删除以及中序遍历,接下来将以 K 模型的结构进行代码编写:

template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};template<class K>class BSTree{typedef BSTreeNode<K> Node;public:bool Insert(const K& key)bool Find(const K& key)bool Erase(const K& key)void InOrder()private:void _InOrder(Node* root)private:Node* _root = nullptr;};

元素插入

将待插入的值与当前节点进行比较:

· 比当前节点小,则移向当前节点的左子节点,。
· 比当前节点的值大,则移向当前节点的右子节点。
· 等于当前节点的值,则不能进行插入,返回false。
· 遍历到节点为空,则当前位置就是要插入位置

bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else {parent->_left = cur;}return true;}

元素查找

首先将要查找的值与当前节点进行比较,根据比较结果选择路径:

· 比当前节点小,则移向当前节点的左子节点。
· 比当前节点大,则移向当前节点的右子节点。
· 等于当前节点,则查找成功,返回当前节点。
· 遍历到结点为空还没找到,则该值不存在,返回空。

bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return true;}}return false;}

元素删除

无孩子,有一个孩子的情况处理起来容易多了,直接将父节点指向当前节点的指针指向该节点的下一节点,然后对当前节点进行销毁即可。

复杂的是有两个孩子的节点

需要在其子树中寻找一个结点替代该结点(左子树的值最大结点/右子树的值最小结点),替换后仍满足搜索树要求

bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 左右都不为空,替换法// 右子树的最左节点代替删除Node* rightminparent = cur;Node* rightmin = cur->_right;while (rightmin->_left){rightminparent = rightmin;rightmin = rightmin->_left;}swap(cur->_key, rightmin->_key);if (rightminparent->_left == rightmin)rightminparent->_left = rightmin->_right;elserightminparent->_right = rightmin->_right;delete rightmin;}return true;}}return false;}

中序遍历

		void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}

附上完整代码:

template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};template<class K>class BSTree{typedef BSTreeNode<K> Node;public:bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else {parent->_left = cur;}return true;}bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return true;}}return false;}bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 左右都不为空,替换法// 右子树的最左节点代替删除Node* rightminparent = cur;Node* rightmin = cur->_right;while (rightmin->_left){rightminparent = rightmin;rightmin = rightmin->_left;}swap(cur->_key, rightmin->_key);if (rightminparent->_left == rightmin)rightminparent->_left = rightmin->_right;elserightminparent->_right = rightmin->_right;delete rightmin;}return true;}}return false;}void InOrder(){_InOrder(_root);cout << endl;}private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;};void TestBSTree1(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t1;for (auto e : a){t1.Insert(e);}t1.InOrder();//t1.Erase(3);t1.Erase(8);t1.InOrder();for (auto e : a){t1.Erase(e);t1.InOrder();}}void TestBSTree2(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t1;for (auto e : a){t1.Insert(e);}t1.InOrder();}
#include"BinarySearchTree.h"int main()
{TestBSTree1();TestBSTree2();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/13172.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

推荐一款3D建模软件:Agisoft Metashape Pro

Agisoft Metashape Pro是一款强大的多视点三维建模设计辅助软件&#xff0c;Agisoft Metashape是一款独立的软件产品&#xff0c;可对数字图像进行摄影测量处理&#xff0c;并生成3D空间数据&#xff0c;用于GIS应用&#xff0c;文化遗产文档和视觉效果制作&#xff0c;以及间接…

IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发

对于新手学习SpringBoot开发&#xff0c;可能最急迫的事情就是尽快掌握数据库的开发。目前数据库开发主要流行使用Mybatis和Mybatis Plus,不过这2个框架对于新手而言需要一定的时间掌握&#xff0c;如果快速上手数据库开发&#xff0c;可以先按照本文介绍的方式使用JdbcTemplat…

Linux高阶——1110—线程安全问题解决方法

1、同步、异步、阻塞、非阻塞 同步过程&#xff1a;发起调用&#xff0c;调用者需要等待被调用者的结果 异步过程&#xff1a;发起调用&#xff0c;无需等待被调用的结果&#xff0c;当有结果后&#xff0c;此结果传出&#xff0c;无需主动获取 阻塞和非阻塞&#xff1a;发起…

STM32cubemx+Proteus仿真和keil5联合调试

前面两步 STM32cubemx生成代码 https://blog.csdn.net/weixin_52733843/article/details/143637304 Proteus新建工程 https://blog.csdn.net/weixin_52733843/article/details/143578853 1 *Proteus仿真联合调试* 在Proteus中&#xff0c;双击STM32F103C6芯片&#xff0c…

初识算法 · 位运算常见总结(1)

目录 前言&#xff1a; 位运算基本总结 部分题目代码 前言&#xff1a; ​本文的主题是位运算&#xff0c;通过常见的知识点讲解&#xff0c;并且会附上5道简单的题目&#xff0c;5道题目的链接分别为&#xff1a;191. 位1的个数 - 力扣&#xff08;LeetCode&#xff09; 1…

visualvm远程连接Docker容器中部署的java应用并监控

visualvm远程连接Docker容器中部署的java应用 前言 jdk1.8中自带了&#xff0c;java11中需要单独下载 下载地址 visualvm下载地址 简介 java虚拟机监控&#xff0c;故障排查及性能分析工具。 网络配置 局域网与docker内网打通&#xff0c;请参考&#xff1a;办公网络与Docker内…

NVIDIA RTX 系统上使用 llama.cpp 加速 LLM

NVIDIA RTX 系统上使用 llama.cpp 加速 LLM 文章目录 NVIDIA RTX 系统上使用 llama.cpp 加速 LLMllama.cpp 概述llama.cpp 在 NVIDIA RTX 上的加速性能使用 llama.cpp 构建的开发人员生态系统使用 llama.cpp 在 RTX 平台上加速的应用程序开始使用 适用于 Windows PC 的 NVIDIA …

信息收集系列(二):ASN分析及域名收集

内容预览 ≧∀≦ゞ 信息收集系列&#xff08;二&#xff09;&#xff1a;ASN分析及域名收集前言一、ASN 分析1. 获取 ASN 码2. 使用 ASNMap 获取 IP 范围3. 将 IP 范围转化为 IP 列表 二、关联域名收集1. 顶级域&#xff08;TLD&#xff09;收集测试方法 2. 根域名收集常用方法…

揭秘:b站可以通过弹幕查询到发送者吗?答案是:不可行

查找发送者 发弹幕被找到 最近&#xff0c;我的一个好兄弟遇到了这样一个问题&#xff1a;他在b站发弹幕&#xff0c;结果被人找到了。他对此很困惑&#xff1a;“发送弹幕不是匿名的吗&#xff1f;只有评论才能看到用户名啊&#xff0c;难道发弹幕也可以被找到吗&#xff1f…

安装mysql、Navicat 17

1.安装mysql 下载地址 https://downloads.mysql.com/archives/installer/ 选择最新版本或者你需要的版本 点击第二个Download下载 下载完毕后双击启动&#xff0c;之后是这个页面 选Custom&#xff08;第四个&#xff09;自定义安装&#xff0c;可以将mysql安装到自定义目录…

人工智能助手是否让程序员技能退化?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

RecyclerView进阶知识讲解

在 Android 开发中&#xff0c;RecyclerView 是一种高效的列表和网格布局控件&#xff0c;用于显示大规模数据。尽管基本使用方法简单&#xff0c;但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面&#xff0c;我将从布局管理、动画和手势、自定义缓存、优化…

测试用例设计方法之判定表

测试用例设计方法之判定表 1. 为什么要有判定表方法2. 什么是判定表3. 判定表法设计用例步骤4. 判定表使用场景 1. 为什么要有判定表方法 案例: 验证"若用户欠费或者关机, 则不允许主被叫"功能的测试 说明: 等价类和边界值分析法主要关注单个输入类条件的测试并未考…

SpringCloud篇(服务拆分 / 远程调用 - 入门案例)

目录 一、服务拆分原则 二、服务拆分示例 1. 案例需求 2. 案例要求 3. 导入SQL语句 4. 实现思路 4.1. 创建父工程 cloud-demo 管理依赖 依赖导入思路 4.2. 创建子工程 order-servic 4.3. 创建子工程 user-servic 4.4. 创建 cloud_order 数据库和表并插入数据 4.5. …

特征融合篇 | YOLO11改进 | 更换上采样方式之轻量级通用上采样算子CARAFE

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。CARAFE算子的主要特点是在保持轻量级功能的同时&#xff0c;能够提供比其他上采样算子更好的性能。它通过少量的参数和计算量来实现高效的图像上采样。CARAFE算子能够根据像素之间的关系进行自适应的上采样&#xff0c;从而…

Java集合Queue——针对实习面试

目录 Java集合QueueQueue接口的特点是什么&#xff1f;Queue和Deque的区别&#xff1f;ArrayDeque和LinkedList的区别&#xff1f;什么是PriorityQueue&#xff1f;什么是BlockingQueue&#xff1f; Java集合Queue Queue接口的特点是什么&#xff1f; Queue接口在Java中是一个…

【支付宝崩了】复盘

一、背景 2024年11月11日&#xff0c;#支付宝崩了#冲上微博热搜第一 部分网友反映支付宝 App无法正常使用&#xff0c;他们遇到了同一笔订单被扣款三次、余额宝转账至余额后余额显示为0、线下支付后商家未收到款项但银行卡已被扣款等问题。 此外&#xff0c;有网友称支付…

丹摩征文活动|FLUX.1+ComfyUI的详细部署以及实验总结

公主请阅 1. FLUX.1的简介2. 部署过程创建资源ComfyUI的部署操作部署FLUX.1 如何使用&#xff1f;实验总结&#xff1a;环境搭建与工具安装实验步骤实验结果分析总结 1. FLUX.1的简介 FLUX.1 是由黑森林实验室开发的图像生成工具&#xff0c;分为三个版本&#xff1a; FLUX-1-…

基于STM32的智能仓库管理系统设计

引言 本项目基于STM32微控制器设计了一个智能仓库管理系统&#xff0c;通过集成多个传感器模块和控制设备&#xff0c;实现对仓库环境和物资管理的自动化监控。该系统能够实时监测仓库内的温湿度、烟雾浓度等参数&#xff0c;并且通过红外传感器监控人员出入&#xff0c;结合R…

206面试题(47~60)

208道Java面试题 47~60 **208道Java面试题****47. 在 Java 程序中怎么保证多线程的运行安全&#xff1f;****48. 多线程中 synchronized 锁升级的原理是什么&#xff1f;****49. 什么是死锁&#xff1f;****50. 怎么防止死锁&#xff1f;****51. ThreadLocal 是什么&#xff1f…