C++: 二叉搜索树及实现

目录

一、二叉搜索树的概念

二、二叉搜索树的操作

2.1插入

2.2删除

1.有左子树,无右子树

2.有右子树,无左子树

3.有左子树和右子树

三、二叉搜索树的实现

要点


前言:为了学习map和set,需要先学二叉搜索树作为铺垫。

一、二叉搜索树的概念

二叉搜索树是一棵二叉树,又称为二叉排序树,它有以下特性:

1.若左子树不为空,则左子树的节点值比根要小

2.若右子树不为空,则右子树的节点值比根要大

3.整棵树都遵循以上规则

需要注意,二叉树也可以是空树。

二、二叉搜索树的操作

2.1插入

插入的思路是,先用递归将树搜索一遍,用key和树的根的节点比大小,比它大往右走,比它小往左走,直到走到空,那么就在空的位置插入。

2.2删除

删除的思路比较复杂。删除情况分三种,分别是所要删除的节点情况,若删除的是key节点:

1.有左子树,无右子树

这里就将key节点的前一个节点,指向它的后一个节点,然后释放key节点。

2.有右子树,无左子树

和上面类似。

3.有左子树和右子树

这里比较复杂,需要将key节点与它的左子树中的最大的一个,或者右子树中最小的一个交换,然后再删除key。

右子树中最小的一个,是第一个右节点的最左的节点。若没有最左节点,那就只能和右节点交换。

交换以后,就可以删除key节点也就是4了。

最后一种无左子树也无右子树可以放在1和2中讨论,归为一种。操作比较简单,此处不再赘述。

三、二叉搜索树的实现

要点

1.为了体现封装,我们只留接口放在类的public中,把具体实现的细节放在private中,这样也方便代码日后维护。同时由于使用递归,所以需要取root的引用,参数就要给root,而在类外是没有办法获取作为私有的root的,因此只能把实现的细节写在private里。

2.搜索二叉树可以用来匹配,比如说当字典使用和门禁系统,这里可以再放入一个类模板。

3.插入的时候要新建一个节点再插入,这里会改变root的地址,所以传引用会更好,不然就要传二级指针了,这个很麻烦,而且在C++中是避免的。

4.删除的时候,要先找到这个节点,再删除。删除时,一共涉及三个指针的操作。建议先理清思路再写代码。

namespace ting
{template<class K, class V>struct BSTreeNode{BSTreeNode(const K& content, const V& value):_content(content),_left(nullptr),_right(nullptr),_value(value){}K  _content;BSTreeNode<K,V>* _left;BSTreeNode<K,V>* _right;V _value;};template<class K, class V>class BSTree{typedef BSTreeNode<K, V> Node;public:bool Insert(const K& key, const V& value){return _Insert(_root, key, value);}Node* Find(const K& key){return _Find(_root, key);}bool Erase(const K& key){return _Erase(_root, key);}void InOrder(){_InOrder(_root);}private:Node* _root = nullptr;Node* _Find(Node* root, const K& key){while (root != nullptr){if (root->_content < key){root = root->_right;}else if (root->_content > key){root = root->_left;}else if (root->_content == key){return root;}}return nullptr;}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_content<<" "<<root->_value << endl;_InOrder(root->_right);}bool _Insert(Node*& root, const K& key, const V& value){if (root == nullptr){/*root->_content = key;root->_value = value;return true;*/root = new Node(key, value);//这里要给root建一个节点return true;}if (root->_content < key){return _Insert(root->_right, key, value);}else if (root->_content > key){return _Insert(root->_left, key, value);}else{return false;}}bool _Erase(Node*& root, const K& key){if (root == nullptr)return false;if (root->_content < key){return _Erase(root->_right, key);}else if (root->_content > key){return _Erase(root->_left, key);}else{Node* del = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{Node* prev = root;Node* minNode = root->_right;while (minNode->_left != nullptr){prev = minNode;minNode = minNode->_left;}root->_content = minNode->_content;root->_value = minNode->_value;if (prev->_left == minNode){prev->_left = minNode->_right;}else{prev->_right = minNode->_right;}del = minNode;}delete del;return true;		}}};void TestBSTree(){BSTree<string, string> dict;dict.Insert("insert", "插入");dict.Insert("erase", "删除");dict.Insert("left", "左边");dict.Insert("string", "字符串");string str;while (cin >> str){auto ret = dict.Find(str);if (ret){cout << str << ":" << ret->_value << endl;}else{cout << "单词拼写错误" << endl;}}string strs[] = { "苹果", "西瓜", "苹果", "樱桃", "苹果", "樱桃", "苹果", "樱桃", "苹果" };// 统计水果出现的次BSTree<string, int> countTree;for (auto str : strs){auto ret = countTree.Find(str);if (ret == NULL){countTree.Insert(str, 1);}else{ret->_value++;}}countTree.InOrder();}
}

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

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

相关文章

基于51单片机的函数发生器设计

一.硬件方案 此函数信号发生器是基于单片机AT89C51设计而成的&#xff0c;能够产生频率范围在0Hz—535Hz的锯齿波、正弦波、三角波、矩形波四种波形&#xff0c;并且能够通过液晶屏1602显示各自的波形类型以及频率数值。电路主要由51单片机最小系统DA0832模数转换模块运放模块…

AI代理的类型、优势及示例

AI 代理的类型、优势和示例 AI 代理是重塑商业动态的关键技术进步。了解这些代理的运作方式&#xff0c;发现它们的关键优势包括效率、可扩展性和成本效益。我们将探索代理的实例及它们在各领域的应用&#xff0c;为未来的人工智能趋势和对客户体验的影响铺平道路。 想象一支由…

`“use strict“`在JavaScript中是什么?它背后的原理是什么?

JavaScript的严格模式(strict mode)是ECMAScript 5引入的一项特性。如果你在脚本或函数的顶部声明 use strict;,你就启用了严格模式: use strict;当JavaScript引擎看到这个指令时,它将开始以一种特殊的模式解释代码。在这种模式下,当检测到某些可能导致潜在错误的编码实…

多重继承引起的二义性问题和虚基类

多重继承容易引起的问题就是因为继承的成员同名而产生的二义性问题。 例&#xff1a;类A和类B中都有成员函数display和数据成员a,类C是类A和类B的直接派生类 情况一&#xff1a; class A {public:int a;void display(); }; class B {public:int a;void display; }; class C:…

添加AXI主IP(AXI4 Lite和AXI4)示例

添加AXI主IP&#xff08;AXI4 Lite和AXI4&#xff09;示例 将等效IP添加到框图中。以下是AXI Central的示例步骤 直接存储器存取&#xff08;CDMA&#xff09;&#xff1a; 1.右键单击方框图中的任意位置&#xff0c;然后选择“添加IP”。 2.搜索并双击AXI Central Direct Memo…

Android 录音AudioRecord

AudioRecord是安卓多媒体框架中用于录制音频的工具。它支持录制原始音频数据&#xff0c;即PCM数据&#xff0c;PCM数据不能被播放器直接播放&#xff0c;需要编码压缩成常见音频格式才能被播放器识别。通常生成PCM文件之后可将PCM文件转成WAV文件一般的播放器便可直接播放了。…

前端开发技巧 --判断文本是否溢出

const isTextOverflower()>{if(element){return element.offsetWidth > element.scrollWidth}return false}实现javascript 判断文本是否溢出

【除了知乎,大家都在逛什么?持续更新~~】

除了知乎&#xff0c;大家都在逛什么&#xff1f; 中文博客琅琊榜 https://github.com/qianguyihao/blog-list 中文博客琅琊榜&#xff0c;只收录优质的中文独立博客&#xff0c;全网最精品。已收录博客数量&#xff1a;328 个博客站点。 这些博主才华横溢&#xff0c;满怀自由…

【2024最新】软考资料大全(免费)

IT行业越来越卷&#xff0c;大家都在忙着搞证&#xff0c;你免费不搞一个&#xff1f; 不管有没有用&#xff0c;有总比没有好噻~ 【初级】&#xff0c;【中级】&#xff0c;【高级】 都有&#xff0c;而且全部免费&#xff0c;全部最新的&#xff01;真题&#xff0c;论文都…

Java查看线上对象的变量值

背影 有时候线上有些配置类&#xff0c;想查看下配置修改是否生效&#xff0c;传统的方法要通过打日志的方法&#xff0c;如果不想通过打日志的方法&#xff0c;有没有好的方案能解决这个问题呢 解决方案 arthas 步骤 得到类加载器的hashcode sc -d com.example.MyService…

眼底项目经验

眼底项目经验 可解释性不足问题眼底项目有多牛逼可解释性不足解法数据、算力、算法都免费送不仅预测当下&#xff0c;还能预测未来和慢病管理整合&#xff0c;形成一个实时健康检测生态 可解释性不足问题 今天下午和腾讯眼底项目人员讨论, 他们不准备做全身性的多疾种, 因为深…

LINUX环境基础练习题(附带答案)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

【typescript - tsc 编译后路径问题/路径别名问题】

这几天在写typescript&#xff0c;遇到个路径依赖问题&#xff0c;编写的.ts文件直接运行OK&#xff0c;但是编译成.js后&#xff0c;运行提示 Error: Cannot find module xxx&#xff0c;&#x1f4dd;记录分析和解决过程 。 问题描述 原始文件&#xff0c;有index.ts 其会引…

小白不知道怎么投稿?记住这个好方法

作为一名单位信息宣传员,我最初踏上这条道路时,满心憧憬着通过文字传递我们单位的精彩瞬间,让社会听见我们的声音。然而,理想与现实之间的距离,却在一次次邮箱投稿的石沉大海中渐渐清晰。那时的我,像所有“小白”一样,以为只要用心撰写稿件,通过电子邮件发给各大媒体,就能收获满…

4 CSS的 变换、过渡与动画

CSS3引入了变换、过渡和动画特性&#xff0c;使得网页可以呈现出丰富的视觉效果和交互体验。通过这些新特性&#xff0c;开发者可以创建复杂的动画效果&#xff0c;而不需要使用JavaScript。 4.1 变换&#xff08;Transforms&#xff09; 变换允许开发者对元素进行旋转、缩放…

Python考试复习--day2

1.出租车计费 mile,waitmap(int,input().split(,)) if mile<3:money13wait*1 elif mile>3 and mile<15:money13(mile-3)*2.3wait*1 else:money1312*2.3(mile-15)*2.3*(10.5)wait*1 print({:.0f}.format(money)) 【知识点1】&#xff1a; map() 函数 【知识点1】&…

代码随想录算法训练营第五十一天|300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组

300.最长递增子序列 dp数组的含义为dp[i]表示字符串以第i位置为末尾的最长递增子序列的长度。 for (int i 1; i < nums.size(); i) {for (int j 0; j < i; j) {if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1);}if (dp[i] > result) result dp[i]; // 取…

设计模式 20 中介者模式 Mediator Pattern

设计模式 20 中介者模式 Mediator Pattern 1.定义 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;它通过封装对象之间的交互&#xff0c;促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象&#xff0c;将系统中对象之间…

Vue中,点击提交按钮,路由多了个问号

问题 当点击提交按钮是路由多了问号&#xff1a; http://localhost:8100/#/ 变为 http://localhost:8100/?#/原因 路由中出现问号通常是由于某些路径或参数处理不当造成的。在该情况下&#xff0c;是因为表单的默认行为导致的。提交表单时&#xff0c;如果没有阻止表单的默…

React Router v6:路由管理的最新进展

React Router v6 是 React 应用程序路由管理的一个重大更新&#xff0c;它引入了许多改进和简化&#xff0c;包括对嵌套路由的更友好处理&#xff0c;以及对钩子函数的使用。 2500G计算机入门到高级架构师开发资料超级大礼包免费送&#xff01; 1. Routes 重构 在 v6 中&…