二叉树进阶 - (C++二叉搜索树的实现)

二叉树进阶 - (二叉搜索树的实现)

  • 二叉搜索树
    • 1. 二叉搜索树概念
    • 2. 二叉搜索树操作
      • 2.1 二叉搜索树的查找
      • 2.2 二叉搜索树的插入
      • 2.3 二叉搜索树的删除(重点)
    • 3. 二叉搜索树的(代码)实现

二叉搜索树

1. 二叉搜索树概念

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

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
    在这里插入图片描述
    在这里插入图片描述

2. 二叉搜索树操作

在这里插入图片描述

int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};

2.1 二叉搜索树的查找

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

从根节点开始,用 cur 指针指向当前节点。
在遍历过程中,比较要查找的值 key 与当前节点的值 cur->_key 的大小关系,根据比较结果来决定继续在左子树还是右子树中查找。
如果要查找的值 key 大于当前节点的值 cur->_key,则继续在当前节点的右子树中查找。
如果要查找的值 key 小于当前节点的值 cur->_key,则继续在当前节点的左子树中查找。
如果要查找的值 key 等于当前节点的值 cur->_key,表示找到了该值,直接返回 true。
当遍历到叶子节点时,仍然没有找到要查找的值,表示该值不存在于树中,返回 false。

2.2 二叉搜索树的插入

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

首先判断根节点 _root 是否为空,如果为空,则将新节点作为根节点,并返回插入成功。
如果根节点不为空,则从根节点开始遍历树来查找合适的插入位置。
在遍历过程中,使用 cur 指针来指向当前节点,parent 指针来指向当前节点的父节点。
如果要插入的值 key 大于当前节点的值 cur->_key,则继续在当前节点的右子树中查找。
如果要插入的值 key 小于当前节点的值 cur->_key,则继续在当前节点的左子树中查找。
如果要插入的值 key 等于当前节点的值 cur->_key,表示值已经存在于树中,不进行插入,直接返回插入失败。
当遍历到叶子节点时,将新节点插入到当前节点的左子树或右子树,根据新节点的值与当前节点的值的大小关系来决定插入到左子树还是右子树。
插入完成后,返回插入成功。

2.3 二叉搜索树的删除(重点)

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:

  • 情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
  • 情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
  • 情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除
    在这里插入图片描述

从根节点开始,用 cur 指针指向当前节点,parent 指针指向当前节点的父节点。
在遍历过程中,比较要删除的值 key 与当前节点的值 cur->_key 的大小关系,根据比较结果来决定继续在左子树还是右子树中查找要删除的节点,并同时记录当前节点的父节点。
如果要删除的值 key 大于当前节点的值 cur->_key,则继续在当前节点的右子树中查找,并更新父节点指针。
如果要删除的值 key 小于当前节点的值 cur->_key,则继续在当前节点的左子树中查找,并更新父节点指针。
如果要删除的值 key 等于当前节点的值 cur->_key,表示找到了要删除的节点。
根据要删除节点的左右子树情况,执行不同的删除操作:
如果要删除的节点的左子树为空,将父节点的右指针指向要删除节点的右子树。
如果要删除的节点的右子树为空,将父节点的左指针指向要删除节点的左子树。
如果要删除的节点的左右子树都不为空,找到要删除节点右子树中的最小节点,将要删除节点的值替换为最小节点的值,然后删除最小节点。
返回 true 表示删除成功。
如果遍历完整棵树都没有找到要删除的节点,返回 false 表示删除失败。

3. 二叉搜索树的(代码)实现


非递归实现

#pragma once
#include <iostream>
using namespace std;
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* cur = _root;Node* parent = nullptr;while (cur){parent = cur;if (key > cur->_key){cur = cur->_right;}else if (key < cur->_key){cur = cur->_left;}else{return false;}}cur = new Node(key);if (key > parent->_key){parent->_right = cur;}if (key < parent->_key){parent->_left = cur;}return true;}//中序打印void InOrder(){_InOrder(_root);cout << endl;}//查找void Find(const K& key){Node* cur = _root;while (cur){if (key > cur->_key){cur = cur->_right;}else if (key < cur->_key){cur = cur->_left;}else{return true;}}return false;}//删除bool Erase(const K& key){Node* cur = _root;Node* parent = nullptr;while (cur){if (key > cur->_key){parent = cur;cur = cur->_right;}else if (key < cur->_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;}}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;}}else{//左右都不为空Node* SubLeft = cur->_right;Node* _parent = cur;while (SubLeft->_left){_parent = SubLeft;SubLeft = SubLeft->_left;}swap(cur->_key, SubLeft->_key);if (SubLeft == _parent->_left){_parent->_left = SubLeft->_right;}else{_parent->_right = SubLeft->_right;}}return true;}}return false;}//析构~BSTree(){Destroy(_root);}//BSTree = default;BSTree(){}//拷贝构造BSTree(const BSTree<K>& t){_root = Copy(t._root);}//赋值拷贝构造BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}
private:Node* Copy(Node* root){if (root == nullptr){return 0;}Node* NewRoot = new Node(root->_key);NewRoot->_left = Copy(root->_left);NewRoot->_right = Copy(root->_right);return NewRoot;}void Destroy(Node*& root){if (root == nullptr){return;}return Destroy(root->_left);return Destroy(root->_right);delete root;root = nullptr; }void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;
};

递归实现

#pragma once
#include <iostream>
using namespace std;
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 findR(const K& key){return _findR(_root, key);}bool InsertR(const K& key){return _InsertR(_root, key);}bool EraseR(const K& key){return _EraseR(_root, key);}void InOrder(){_InOrder(_root);cout << endl;}//析构~BSTree(){Destroy(_root);}//BSTree = default;BSTree(){}//拷贝构造BSTree(const BSTree<K>& t){_root = Copy(t._root);}//赋值拷贝构造BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}
private:Node* Copy(Node* root){if (root == nullptr){return 0;}Node* NewRoot = new Node(root->_key);NewRoot->_left = Copy(root->_left);NewRoot->_right = Copy(root->_right);return NewRoot;}void Destroy(Node*& root){if (root == nullptr){return;}return Destroy(root->_left);return Destroy(root->_right);delete root;root = nullptr; }//递归实现删除bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false;}if (key < root->_key){return _EraseR(root->_left, key);}else if (key > root->_key){return _EraseR(root->_right, key);}else{if (root->_left == nullptr){Node* del = root;root = root->_right;delete del;return true;}else if (root->_right == nullptr){Node* del = root;root = root->_left;delete del;return true;}else{Node* SubLeft = root->_right;while (SubLeft->_left){SubLeft = SubLeft->_left;}swap(root->_key, SubLeft->_key);//转换在子树中去递归删除   return _EraseR(root->_right, key);}}}//递归实现插入bool _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key);return true;}if (key > root->_key){return _InsertR(root->_right, key);}if (key < root->_key){return _InsertR(root->_left, key);}else{return false;}}//递归实现查找bool _findR(Node* root, const K& key){if (root == nullptr){return false;}else if (key > root->_key){return _findR(root->_right, key);}else if (key < root->_key){return _findR(root->_left, key);}else{return true;}}//中序遍历打印void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;
};

(本章完)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板

一、购买域名并且进行备案和解析&#xff0c;正常情况下&#xff0c;购买完域名&#xff0c;如果找不到去哪备案&#xff0c;可以在腾讯云上搜索“备案”关键词就会出现了&#xff0c;所以这里不做详细介绍&#xff0c;直接进行步骤提示&#xff1a; 二、申请ssl证书&#xff0…

diffusers-Load adapters

https://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adaptershttps://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adapters 有几种训练技术可以个性化扩散模型&#xff0c;生成特定主题的图像或某些风格的图像。每种训练方法都会产…

关于嵌入式rtthread系统与单片机芯片

简介 我估计已经有很久没更新了&#xff0c;近一年都在某个国企里工作&#xff0c;我做的就是嵌入式工程师的岗位&#xff0c;最近才刚刚退出来&#xff0c;想来说说自己的工作使用的软件和系统。 本身进公司的时候&#xff0c;其实做的就是写单片机的板子的程序的工作&#x…

mysql迁移data目录(Linux-Centos)

随着时间的推移&#xff0c;mysql的数据量越越大&#xff0c;使用yum默认安装的目录为系统盘 /var/lib/mysql&#xff0c;现重新挂载了一个硬盘&#xff0c;需要做数据目录的迁移到 /mnt/data/。以解决占用系统盘过高情况。 1.强烈建议这种操作。镜像一个一样的Centos系统&…

基于springboot实现游戏分享网站系统项目【项目源码+论文说明】

基于springboot实现游戏分享网站演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到…

canvas实现环形进度条

与setTimeout和setInterval不同&#xff0c;requestAnimationFrame不需要设置时间间隔。 效果图 源代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Canvas progress</title> </head&g…

软件测试/测试开发丨ChatGPT能否成为PPT最佳伴侣

点此获取更多相关资料 简介 PPT 已经渗透到我们的日常工作中&#xff0c;无论是工作汇报、商务报告、学术演讲、培训材料都常常要求编写一个正式的 PPT&#xff0c;协助完成一次汇报或一次演讲。PPT相比于传统文本的就是有布局、图片、动画效果等&#xff0c;可以给到观众更好…

Qt 窗口无法移出屏幕

1 使用场景 设计一个缩进/展开widget的效果&#xff0c;抽屉效果。 看到实现的方法有定时器里move窗口&#xff0c;或是使用QPropertyAnimation。 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint |Qt::X11BypassWindowManagerHint&#xff09;&#xff1b; 记得在移…

linux笔记总结-基本命令

参考&#xff1a; 1.Linux 和Windows比 比较 &#xff08;了解&#xff09; 1. 记住一句经典的话&#xff1a;在 Linux 世界里&#xff0c;一切皆文件 2. Linux目录结构 /lib • 系统开机所需要最基本的动态连接共享库&#xff0c;其作用类似于Windows里的DLL文件。几 乎所有…

企业采用生成式人工智能需要考虑什么

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 最近&#xff0c;各行业采用人工智能生成内容&#xff08;AIGC&#xff09;的趋势显着。这种变革性技术的一些著名实施包括Notion AI…

玩一下Spring Boot

文章目录 1 开发环境1.1 JDK1.2 IntelliJ IDEA2 Spring Boot2.1 创建项目2.2 创建模板页面2.3 创建控制器2.4 启动项目2.5 访问页面1 开发环境 1.1 JDK 安装JDK21 配置环境变量 在命令行查看JDK版本 玩一玩jshell

Windows 11 Home 中启用 Hyper-V

Hyper-V 是微软开发的基于硬件的虚拟机管理程序。它允许用户在 Windows 操作系统之上运行不同操作系统的多个实例。目前&#xff0c;Hyper-V 也支持 Windows、Ubuntu 和其他 Linux 发行版。 如果发现像我这样电脑上启用Hyper-V选项可以按照以下步骤进行操作。 一、新建一个txt…

Mysql系列-索引类型

一 、索引类型别 根据叶子节点的内容分类的索引类型 InnoDB 使用B tree 索引模型&#xff0c;根据叶子节点是否存储数&#xff08;根据叶子节点的内容&#xff09;分为主键索引和非主键索引&#xff1b;非主键索引包括&#xff1a;普通索引、唯一索引、组合索引主键索引的叶子…

Docker(1)

文章目录 Docker物理机部署的缺点虚拟机Docker 与虚拟机的区别Docker 的优势 Docker 概念安装 DockerDocker 架构镜像加速Docker 命令进程服务相关命令 镜像相关文件命令容器相关的命令 镜像加载的原理UnionFS(联合文件系统)docker 镜像加载原理 容器的数据卷数据卷概念配置数据…

数据库实验:SQL的数据定义与单表查询

目录 实验目的实验内容实验要求实验过程实验步骤实例代码结果示意 数据库的实验&#xff0c;对关系型数据库MySQL进行一些实际的操作 实验目的 (1) 掌握DBMS的数据定义功能 (2) 掌握SQL语言的数据定义语句 (3) 掌握RDBMS的数据单表查询功能 (4) 掌握SQL语言的数据单表查询语句…

这两天公司面了一个字节来的要求月薪23K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

魔术般的速度,焕然一新的磁盘空间 - Magic Disk Cleaner for Mac 2023

在当今这个信息时代&#xff0c;我们的磁盘空间无时无刻不在被各种文件和数据所填满。无论是工作文件&#xff0c;还是日常生活的照片、视频&#xff0c;亦或是下载的各种应用程序&#xff0c;都在不断地蚕食着我们的磁盘空间。面对这种情况&#xff0c;一款高效、便捷的磁盘垃…

springboot整合七牛云oss操作文件

文章目录 springboot整合七牛云oss操作文件核心代码&#xff08;记得修改application.yml配置参数⭐&#xff09;maven依赖QiniuOssProperties配置类UploadControllerResponseResult统一封装响应结果ResponseType响应类型枚举OssUploadService接口QiniuOssUploadServiceImpl实现…

PerfectPixel 插件,前端页面显示优化工具

1.简介 PerfectPixel 插件是一款适用于 Chrome 浏览器的网页前端页面显示优化工具&#xff0c;该插件能够帮助开发人员和标记设计人员在开发时将设计图直接加载至网页中&#xff0c;与已成型的网页进行重叠对比&#xff0c;以规范网页像素精度 作为一款可以优化前端页面显示的…

Idea快速生成测试类

例如写写完一个功能类,需要对里面方法进行测试 在当前页面 按住CTRLSHFITT 选择你要生成的测试方法 点击OK,就会在test目录下在你对应包下生成对应测试类