【C++】简易二叉搜索树

目录

一、概念:

二、代码实现:

大致结构:

1、遍历:

2、insert

3、find

4、erase

三、总结:


一、概念:

        二叉搜索树又称为二叉排序树,是一种具有特殊性质的二叉树,对于每一个节点而言,节点的左子树要比节点的值小,节点的右子树要比节点的值大,也就是说节点的左右子树也是二叉搜索树。

例如如下二叉树:

拿根节点8来讲,8的左子树都是比8小的值,而8的右子树都是比8大的值,与此同时,8的左右子树也是二叉搜索树,拿8的左子树的根节点3来讲,3的左子树都是比3大的值,3的右子树都是比3小的值。以此反复。

二、代码实现:

大致结构:

// 二叉树的节点: 
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:Node* _root = nullptr; // 根节点
};

1、遍历:

        前面说过,在搜索二叉树中对于每一个节点而言,比它大的值在右边,比它小的值在左边,这种特性如果用二叉树的中序遍历打印出来的就是一个有序的数列,所以搜索二叉树的遍历可以直接写中序遍历,但要注意的是,在上面的大致结构中二叉搜索树的类中的根节点是私有的,而中序遍历又需要用到根节点,所以我们可以直接嵌套一层:

template<class K>
class BSTree
{typedef BSTreeNode<K> Node;public:// 其他成员函数void InOrder(){_InOrder(_root);}
private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->left);cout << root->_key << " ";_InOrder(root->right);}private:Node* _root = nullptr;
};

2、insert

        值插入需要从根节点开始往下遍历到空位置(比节点大的往右走,比节点小的往左走),需要注意的是,期间如果遇到相同的值(也就是重复的情况)就可以不用进行插入了,因为搜索树不支持冗余。

        思路:如果树为空,那么直接定义一个节点即可,不为空则设置一个指针cur指向根节点并往下遍历,注意cur注定会走到空,所以要多设置一个指针parent代表cur的父节点。最后如果插入值比父节点大则是parent的右孩子,否则就是左孩子。

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

代码测试:

// 往搜索树中插入一段数据,然后遍历出来(搜索树的中序遍历出来是有序的数列)
int main()
{int a[] = { 8,3,1,10,6,4,7,14,13 };BSTree<int> t1;for (int i : a){t1.insert(i);}t1.InOrder();
}

3、find

        值查找就是从根节点向下遍历,比节点值大的往右走,比节点值小的往左走,找到返回true找不到返回false。

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

4、erase

搜索二叉树的删除值操作分为好几种情况,以下一一列举:

情况一:无左右孩子,例如节点 4、7、13,这种就可以直接删除。(这里有一种特殊情况需要特殊处理,那就是整棵树只有这一个节点,需要把该节点置空,不能直接删)

情况二:只有左孩子或者只右孩子,例如节点 10、14,这种需要记录其父节点,然后让其父节点指向自己的孩子节点,再删除该节点。

情况三:节点的左右孩子同时存在,例如节点8,3,6,此时需要用到替换法(以节点8为例),用该节点的左子树最大的值(7)或者右子树最小的值(10)替换该节点,然后再删除被替换的节点即可(此时还需注意被替换的点还有没有孩子,有的话删除前还需要将被替换节点的孩子交给被替换节点的父节点保管)。(也就是左子树找最右的叶子节点或者右子树找最左的叶子节点)

代码实现:

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* leftMaxParent = cur;Node* leftMax = cur->left;while (leftMax->right){leftMaxParent = leftMax;leftMax = leftMax->right;}swap(cur->_key, leftMax->_key);// 更改子节点指向if (leftMax == leftMaxParent->left) leftMaxParent->left = leftMax->left;else leftMaxParent->right = leftMax->left;delete leftMax;}return true;}}return false;
}

三、总结:

二叉搜索树的应用场景:

K模型:K模型即只有Key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。

例如:

        构建一棵二叉搜索树,将词库中的每个单词作为Key,然后输入一个单词word,判断该单词是否拼写正确。就是在树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

KV模型:每一个关键码Key,都有与之对应的值Value,即<Key,Value>的键值对。

例如英汉字典就是一种英文与中文的对应关系,英文单词与其对应的中文<word,chinese>就构成一种键值对。将其存入树中,输入英文就可以返回对应中文。     

二叉搜索树的性能效率:

        在对二叉搜索树进行insert或是erase时都先必须进行find操作,因此find的效率也就代表了各个操作的性能。但是这也取决于树的形状。

最优情况下:二叉搜索树为完全二叉树(或者接近完全二叉树),效率为O(logn)

最差情况下:二叉搜索树退化为单支树(或者类似单支),效率为O(n)

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

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

相关文章

在虚拟环境中找到Qt Designer

Pyqt5中找到Qt Designer 安装Pyqt5和Qt Designer: pip install pyqt5-tools 假设Python的虚拟环境名为:d2l &#xff0c;虚拟环境在d2l文件夹中 D:\Software\d2l\Lib\site-packages\qt5_applications\Qt\bin 双击Qt designer启动 Pyside2中找到Qt Designer d2l是虚拟环境…

上位机图像处理和嵌入式模块部署(树莓派4b下使用sqlite3)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 嵌入式设备下面&#xff0c;有的时候也要对数据进行处理和保存。如果处理的数据不是很多&#xff0c;一般用json就可以。但是数据如果量比较大&…

rust前端web开发框架yew使用

构建完整基于 rust 的 web 应用,使用yew框架 trunk 构建、打包、发布 wasm web 应用 安装后会作为一个系统命令&#xff0c;默认有两个特性开启 rustls - 客户端与服务端通信的 tls 库update_check - 用于应用启动时启动更新检查&#xff0c;应用有更新时提示用户更新。nati…

Linux——终端

一、终端 1、终端是什么 终端最初是指终端设备&#xff08;Terminal&#xff09;&#xff0c;它是一种用户与计算机系统进行交互的硬件设备。在早期的计算机系统中&#xff0c;终端通常是一台带有键盘和显示器的电脑&#xff0c;用户通过它输入命令&#xff0c;计算机在执行命…

Swift中的单例

在Swift中实现单例模式可以通过使用静态常量或静态变量来实现。下面是一个示例&#xff1a; class Singleton {static let sharedInstance Singleton()private init() {// 这里是初始化代码}// 这里是其他实例方法和属性 }在上面的示例中&#xff0c;通过使用static let来创建…

SpringBoot引入Layui样式总是出现404

一般出现Layui样式文件如css&#xff0c;js404的错误 解决方案 &#xff08;1&#xff09;首先将其中的静态资源下载resources/static中 &#xff08;2&#xff09;在启动类中重写方法 package com.gq.booksystem;import org.mybatis.spring.annotation.MapperScan; import …

商城数据库(1-4)

1——商家认证项目表&#xff08;wang_accreds&#xff09; CREATE TABLE wang_accreds (accredId int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,accredName varchar(50) NOT NULL COMMENT 名称,accredImg varchar(150) NOT NULL DEFAULT 0 COMMENT 图标,dataFlag tinyint…

centOS 7.9操作

名称日期版本作者centOS7.9操作2024.4.271.0lll 实验题目&#xff1a; 创建一个用户。 在创建的用户中再创建一个2024的目录。 在2024的下在创建一个 1---10的目录&#xff0c;再创建一个a--z.txt的文件。 在创建一个2024bak的目录。 再将当前用户的所有文件备份到2024ba…

【算法学习】线段树基础版

一 线段树 1.概念 线段树可以理解为一个二叉树&#xff0c;如果是利用线段树求区间的和&#xff0c;那么每个结点的权值维护的是结点所维护区间的和&#xff0c;再将该区间一分为二&#xff0c;分别交由左右儿子维护。 拿区间1 - 4的和来举例子&#xff0c; 根结点维护的是区…

开发管理导读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、代码版本管理1、github代码版本管理2、gitlab代码版本管理3、SVN&#xff08;Subversion&#xff09;代码版本管理 二、代…

JavaEE——Spring Boot入门

目录 &#x1f4da; JavaEE——Spring Boot入门 &#x1f527; 1. 新建Spring Boot项目 &#x1f6e0; 2. 添加pom依赖 &#x1f4dd; 3. 添加application.yml文件 &#x1f4c2; 4. 创建Dao层 &#x1f527; 5. 创建Service层 &#x1f5a5;️ 6. 创建Controller层及HT…

【小浩算法cpp题解】合并两个有序链表(21)

目录 前言我的思路我的代码 前言 今天继续做链表相关的题目&#xff0c;考研期间练多了现在觉得这种题目真是简单。晚上如果有机会可以再做一个树的深度优先搜索。 我的思路 其实这道题的思路比较像排序中的二路归并&#xff0c;最核心的点是在归并的时候要防止断链,我的解决…

librosa 语音识别 学习笔记

目录 不错的功能介绍 librosa安装 语音识别 不错的功能介绍 librosa&#xff0c;一个很有趣的 Python 库&#xff01; - 简书 音频转特征向量 GitHub - librosa/librosa: Python library for audio and music analysis librosa安装 2024.04.27 测试ok Win11系统 pip in…

使用ClassFinal实现springboot项目jar包加密

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

docker容器技术篇:集群管理实战mesos+zookeeper+marathon(二)

docker集群管理实战mesoszookeepermarathon&#xff08;二&#xff09; 一 实验环境 操作系统&#xff1a;centos7.9 二 基础环境配置以及安装mesos 安装过程请点击下面的链接查看&#xff1a; 容器集群管理实战mesoszookeepermarathon&#xff08;一&#xff09; 三 安装…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 4月27日,星期六

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年4月27日 星期六 农历三月十九 1、 教育部&#xff1a;深入实施学生欺凌防治专项行动&#xff0c;对所有中小学校开展起底式大排查。 2、 商务部等七部门联合印发《汽车以旧换新补贴实施细则》&#xff0c;购车最高补贴1万…

【VBA】获取指定目录下的Excel文件,并合并所有excel中的内容。

1.新建一个excel表格。并创建两个Sheet&#xff0c;名字分别命名为FileList 和 All information。 2.按ALTF11进入 VBA编程模块&#xff0c;插入模块。 3.将如下 第五部分代码复制到模块中。 点击运行即可&#xff0c;然后就能提取指定目录下的所有excel文件信息并合并到一起…

连接oracle时出现ORA-12541:TNS:无监听程序的错误

遇到个问题&#xff0c;有一台windows serve 的服务器&#xff0c;这台服务器&#xff08;只部署了oracle&#xff09;忽然监听出问题了&#xff0c;提示 一、问题检查步骤&#xff1a; 1.winR--->cmd--->输入 lsnrctl status 查看监听的状态 如果监听器未运行&#…

【01】JAVASE-Java基础入门【从零开始学JAVA】

Java零基础系列课程-JavaSE基础篇 Lecture&#xff1a;波哥 Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。…

移远通信再推系列高性能卫星、5G、GNSS及三合一组合天线

4月23日&#xff0c;全球领先的物联网整体解决方案供应商移远通信正式宣布&#xff0c;再次推出多款高性能天线产品&#xff0c;以进一步满足物联网市场对高品质天线产品的需求。 其中包括卫星天线YETN001L1A、三合一组合天线YEMA300QXA和YEMN302Q1A&#xff0c;外部5G天线YECN…