C++实现二叉搜索树(模型)

目录

1.二叉搜索树的概念

2.二叉搜索树的实现

2.1总体代码预览

2.2各个函数实现原理

链表结构体

二叉搜索树的成员变量

二叉搜索树的插入

二叉搜索树的查找

二叉搜索树的遍历

二叉搜索树的删除


1.二叉搜索树的概念

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

1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

3.它的左右子树也分别为二叉搜索树

2.二叉搜索树的实现

由上面的定义,我们知道二叉搜索树的左孩子是小于父亲的,而右孩子是大于父亲的。由这个规律我们就可以实现一下这个二叉搜索树。

2.1总体代码预览

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 BST{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 (key > cur->_key){parent = cur;cur = cur->_right;}else if (key < cur->_key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key);if (key < parent->_key){parent->_left = cur;}else{parent->_right = cur;}return true;}bool 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* parent = nullptr;Node* cur = _root;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 (parent->_left == cur){parent->_left = cur->_right;}else if (parent->_right == cur){parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (parent->_left == cur){parent->_left = cur->_left;}else if (parent->_right == cur){parent->_right = cur->_left;}}delete cur;}//cur左右都不为空else{Node* rightminparent = cur;Node* rightmin = cur->_right;while (rightmin->_left){rightminparent = rightmin;rightmin = rightmin->_left;}swap(rightmin->_key, cur->_key);if(rightminparent->_left== rightmin)rightminparent->_left = rightmin->_right;elserightminparent->_right = rightmin->_right;delete rightmin;}return true;}}return false;}void InOrder(){_InOrder(_root);}private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << endl;_InOrder(root->_right);}Node* _root=nullptr;};

2.2各个函数实现原理

链表结构体

template<class k>struct BSTreeNode{BSTreeNode<k>* _left;BSTreeNode<k>* _right;k _key;BSTreeNode(const k& key):_left(nullptr),_right(nullptr),_key(key){}};

既然是我们的二叉树,那么链表的部分肯定是不能少的吧,这个链表里面,我们来定义左右孩子的指针,还有用来进行标识的key值,接下来就可以写一下它的构造函数,这个节点一开始肯定是没有左右孩子的,所以我们给它们赋上空指针,而key就是我们传的key。

二叉搜索树的成员变量

Node* _root=nullptr;

二叉搜索树的成员变量就很简单了,我们直接定义一个结构体指针的变量的就可以了。Node类型是我们重命名链表名后的名字。

二叉搜索树的插入

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

插入的逻辑其实非常简单,如果这棵树是一棵空树,那么我们直接创个根节点就可以了,不需要后续的操作,倘若不是空树,那我们就进行接下来的操作,我们先定义一个父亲节点parent和当前节点cur,然后按照我们的性质,key比cur中的大我们就往右,小的话我们就往左走,如果这个key在树中存在,我们就放回false,因为set是有去重功能的,就是说一棵树里不能存在两个一样的值。找到了适合的位置我们就出循环,然后开始创建节点,进行连接就可以了。

二叉搜索树的查找

bool 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;}

查找的功能就更简单了,我们只需要按照性质,左边比根小右边比根大就可以了。

二叉搜索树的遍历

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

我们的二叉搜索树按照中序遍历是刚好是有序的,这个是我们二叉搜索树的意义之一,所以我们这里也是实现中序遍历。

中序遍历的思想就简单的多了,使用递归对它的各个节点进行遍历就可以了。

但是我们调用中序遍历肯定不想别人传个参数,所以我们再进行封装就可以了。

二叉搜索树的删除

bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;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 (parent->_left == cur){parent->_left = cur->_right;}else if (parent->_right == cur){parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (parent->_left == cur){parent->_left = cur->_left;}else if (parent->_right == cur){parent->_right = cur->_left;}}delete cur;}//cur左右都不为空else{Node* rightminparent = cur;Node* rightmin = cur->_right;while (rightmin->_left){rightminparent = rightmin;rightmin = rightmin->_left;}swap(rightmin->_key, cur->_key);if(rightminparent->_left== rightmin)rightminparent->_left = rightmin->_right;elserightminparent->_right = rightmin->_right;delete rightmin;}return true;}}return false;}

二叉搜索树的删除才是我们的真正难点

我们最开始的操作还是一样的,我们要找那个被删除的节点,找到后就开始我们的操作了。我们有三种大情况:

第一种是要删除的节点左孩子为空的时候:

如图所示,我们的cur只有一边是有值的,这个时候我们先判断这个cur是父亲的左孩子还是右孩子,然后再把链表指向修改就行了,但是不要忘记了,我们的cur有可能是根节点,这个时候我们的父亲节点是空,这个时候是没法去给parent修改指向的,所以我们要单独的写一个判断。

第二种自然就是右孩子为空了,思路跟左孩子是一模一样的。

第三种就是我们的cur的左右孩子都不为空,这里的做法右两种,第一种是找cur的左子树的最大值,替换cur,然后再把cur给删除,第二种是找右子树的最小值,然后进行同样的操作,这两种做法都可以使其保持二叉搜索树该有的性质。这里我们选择第二种。

可以看到外面用循环来找到右子树的最小值,找到后交换值,我们没有直接让rightminparent的左节点直接接向rightmin的右子树是因为可能有这种情况

假如我们删的是8,这个时候右孩子是没有左节点的,这个时候我们就不可能rightminparent的左节点接向rightmin的右子树,所以我们进行了这个分类讨论,这个细节也是很难想到的。

至此我们的二叉搜索树的实现原理就讲完了,感谢大家的收看!

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

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

相关文章

AI去衣技术在动画制作中的应用

随着科技的发展&#xff0c;人工智能&#xff08;AI&#xff09;已经在各个领域中发挥了重要作用&#xff0c;其中包括动画制作。在动画制作中&#xff0c;AI去衣技术是一个重要的工具&#xff0c;它可以帮助动画师们更加高效地完成工作。 AI去衣技术是一种基于人工智能的图像…

jenkins目录下的vue3项目——pnpm install后运行报错——奇葩问题解决

昨天到今天&#xff0c;同事那边遇到一个问题&#xff0c;就是关于vue3vite的项目&#xff0c;在执行了自动打包后&#xff0c;运行代码会提示报错的问题。 报错信息如下&#xff1a; 具体错误信息如下&#xff1a; ERROR 11:28:14 [vite] Pre-transform error: Cannot find …

C语言实战项目---通讯录

项目要实现的内容&#xff1a;能够存放100个人的通讯录程序&#xff0c;能够实现联系人数据的存储&#xff0c;删除&#xff0c;修改&#xff0c;查找&#xff0c;展示联系人的信息。 所需知识&#xff1a;结构体&#xff0c;指针&#xff0c;函数................. 废话不多…

AI绘画成果展(第一期)

免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。 免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。

pandas索引

pandas索引 一、索引1.1 建立索引1.2 重置索引1.3 索引类型1.4 索引的属性1.5 索引的操作 一、索引 1.1 建立索引 建立索引可以在数据读取加载中指定索引&#xff1a; import pandas as pd df pd.read_excel(team.xlsx, index_colname) # 将name列设置为索引 df.head()效…

Hadoop3:HDFS的架构组成

一、官方文档 我这里学习的是Hadoop3.1.3版本&#xff0c;所以&#xff0c;查看的也是3.1.3版本的文档 Architecture模块最下面 二、HDFS架构介绍 HDFS架构的主要组成部分&#xff0c;是一下四个部分 1、NameNode(NN) 就是Master节点&#xff0c;它是集群管理者。 1、管…

解决 SyntaxError: Unexpected token ‘.‘ 报错问题

这个报错一般是编译问题&#xff0c;浏览器的版本过低没通过代码 解决办法&#xff1a; 在package.json文件中加上这个 "browserslist": ["> 1%","last 2 versions","not dead","not ie < 6","Android > 4&…

Web 3.0时代:软文发稿对企业品牌的影响

Web 3.0的到来&#xff0c;标志着我们已经进入了一个全新的互联网时代。在这个新时代中&#xff0c;信息的生成和传播有了更多的可能性和更广的空间。作为企业品牌宣传的重要手段之一的软文发稿&#xff0c;在Web 3.0时代将会面临什么样的挑战和机遇&#xff1f; 首先&#xf…

人脸美型SDK解决方案,适用于各类应用场景

视频内容已经成为企业宣传、产品展示、互动直播等多个领域的核心载体。而在这些场景中&#xff0c;高质量的人脸美型效果不仅能够提升用户体验&#xff0c;更能为品牌加分。美摄科技凭借深厚的技术积累和行业洞察&#xff0c;推出了全新的人脸美型SDK解决方案&#xff0c;为企业…

Fizzler库+C#:从微博抓取热点的最简单方法

概述 在这篇技术文章中&#xff0c;我们将深入研究如何利用Fizzler库结合C#语言&#xff0c;以实现从微博平台抓取热点信息的功能。微博作为中国乃至全球范围内具有重要影响力的社交媒体平台之一&#xff0c;在互联网信息传播中扮演着举足轻重的角色。通过Fizzler这一强大的.N…

Sarcasm detection论文解析 |CAT-BiGRU

论文地址 论文地址&#xff1a;CAT-BiGRU: Convolution and Attention with Bi-Directional Gated Recurrent Unit for Self-Deprecating Sarcasm Detection | Cognitive Computation github:Ashraf-Kamal/Self-Deprecating-Sarcasm-Detection (github.com) 论文首页 笔记框架 …

什么软件能在桌面提醒我 电脑桌面提醒软件

在这个信息爆炸的时代&#xff0c;我们每个人每天都需要处理海量的信息和任务。有时候&#xff0c;即便是再细心的人&#xff0c;也难免会因为事情太多而忘记一些重要的细节。 我就经常遇到这样的问题&#xff0c;明明记得自己有个重要的会议要参加&#xff0c;或者有个关键的…

LeetCode 每日一题 Day 144-157

2385. 感染二叉树需要的总时间 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟&#xff0c;感染 将会从值为 start 的节点开始爆发。 每分钟&#xff0c;如果节点满足以下全部条件&#xff0c;就会被感染&#xf…

风电厂数字孪生3D数据可视化交互展示构筑智慧化电厂管理体系

随着智慧电厂成为未来电力企业发展的必然趋势&#xff0c;深圳华锐视点紧跟时代步伐&#xff0c;引领技术革新&#xff0c;推出了能源3D可视化智慧管理系统。该系统以企业现有的数字化、信息化建设为基础&#xff0c;融合云平台、大数据、物联网、移动互联、机器人、VR虚拟现实…

什么是视频号小店?为什么这么多人都在做?一文带你轻松入门!

大家好&#xff0c;我是电商花花。 现在电商的快速发展&#xff0c;电商行业在各大电商平台上不断发展&#xff0c;而视频号小店也被更多人看到和入驻&#xff0c;让更多创业者对视频号小店产生兴趣。 知道的人都觉得视频号小店是一个不可多得的创业项目&#xff0c;因为这里…

开源的聊天服务器tigase 7.1.3 相关文档

官方的api文档 7.1.3&#xff1a; Tigase Administration Guide github地址&#xff1a; Release 7.1.3 tigase/tigase-server GitHub 安装教程&#xff1a; Tigase手动安装过程-腾讯云开发者社区-腾讯云

学习强国手机助手

前景&#xff1a; 用手机刷学习强国时要一直盯着手机&#xff0c;总感觉费时费劲&#xff0c;刚好最近学习python写个小工具帮忙自动学习&#xff0c;实现了文章和视频学习&#xff0c;答题类不一定都能正确。上班时电脑连着USB就可以放那&#xff0c;自己可以上班干自己事情。…

IDEA中git的常用操作(保姆级教学)

IDEA中git的常用操作&#xff08;保姆级教学&#xff09; 以下是git的工作原理&#xff0c;觉得繁琐的可以跳过不看 Workspace&#xff1a;工作区 (平时存放代码的地方) Index / Stage&#xff1a;暂存区&#xff08;用于临时存放存放你的改动&#xff0c;事实上就是一个文件&…

SemCity: 一个应用于真实户外环境场景生成的3D Diffusion模型

论文标题&#xff1a; SemCity: Semantic Scene Generation with Triplane Diffusion 论文作者&#xff1a; Jumin Lee1, Sebin Lee1, Changho Jo, Woobin Im, Juhyeong Seon, Sung-Eui Yoon 项目地址&#xff1a;https://sglab.kaist.ac.kr/SemCity/ 前言&#xff1a; 该论…

JVM笔记-常用命令

1、jstat jstat是一个极强的监视JVM的工具&#xff0c;可以用来监视JVM的各种堆和非堆的大小以及内存使用量。 Usage: jstat -help|-optionsjstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]jstat的常用用法如图所示&#xff…