数据结构:二叉搜索树(非递归实现)

目录

1、二叉搜索树

2、二叉搜索树的相关操作。

1、查找

2、插入

3、删除

3、代码实现(非递归)


1、二叉搜索树

二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树,其中每个节点的值大于其左子树中所有节点的值,小于其右子树中所有节点的值。这种特性使得二叉搜索树具有快速的查找、插入和删除操作。

二叉搜索树的性质包括:

  1. 左子树中所有节点的值小于根节点的值;
  2. 右子树中所有节点的值大于根节点的值;
  3. 左右子树也分别为二叉搜索树。

如下图所示:

                                           

2、二叉搜索树的相关操作。

1、查找

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

2、插入

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

3、删除

删除操作也是最值得思考的操作,因为有四种情况

a. 要删除的结点无孩子结点
这是最简单的情况,直接删除节点就好,并且将该节点的父节点对应的指针置为nullptr
b. 要删除的结点只有左孩子结点
如果为根节点,那么直接让该节点的左孩子变为根节点即可。
如果不为根节点,那么需要判断该节点是prev(该节点的父节点)的左孩子还是右孩子,让对应的指针指向该节点的左孩子即可。
c. 要删除的结点只有右孩子结点
如果为根节点,同上操作,只是变为对该节点右孩子的操作
不为根节点,判断该节点是prev(该节点的父节点)的左孩子还是右孩子,让对应的指针指向该节点的右孩子即可。
d. 要删除的结点有左、右孩子结点
如果该节点有左孩子和右孩子,那么如何操作才能在不破坏二叉搜索树结构的情况下完成删除呢?
我们需要找到该节点的 最小右孩子来替换该节点,这样就可以解决问题。
最小右孩子:
最小右孩子分为两种情况:
1.当前节点的右孩子节点的最小左孩子
2.若是当前节点的右孩子节点没有最小左孩子,那么当前节点的右孩子节点就是最小右孩子。
下面是一段代码 实现,cur就是 当前要删除的节点,我们将它设为初始的最小右孩子的父节点,然后while循环查找最小左孩子,最后判断最小右孩子是该父节点的左右指针,将对应指针指向RightMin->_right;
						Node* RightMinParent = cur;Node* RightMin = cur->_right;while (RightMin->_left){RightMinParent = RightMin;RightMin = RightMin->_left;}cur->_key = RightMin->_key;if (RightMin == RightMinParent->_left){RightMinParent->_left = RightMin->_right;}else{RightMinParent->_right = RightMin->_right;}delete RightMin;return true;

3、代码实现(非递归)

二叉搜索树的实现:

1.  K 模型: K 模型即只有 key 作为关键码,结构中只需要存储 Key 即可,关键码即为需要搜索到
的值
比如: 给一个单词 word ,判断该单词是否拼写正确 ,具体方式如下:
以词库中所有单词集合中的每个单词作为 key ,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
2. KV 模型:每一个关键码 key ,都有与之对应的值 Value ,即 <Key, Value> 的键值对 。该种方
式在现实生活中非常常见:
比如 英汉词典就是英文与中文的对应关系 ,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese> 就构成一种键值对;
再比如 统计单词次数 ,统计成功后,给定单词就可快速找到其出现的次数, 单词与其出
现次数就是 <word, count> 就构成一种键值对
#pragma once
namespace key_value
{template<class K, class V>struct BSTreeNode{typedef BSTreeNode<K, V> Node;Node* _left;Node* _right;K _key;V _value;BSTreeNode(const K& key, const V& value):_left(nullptr),_right(nullptr),_key(key),_value(value){}};template<class K,class V>class BSTree{typedef BSTreeNode<K, V> Node;public:bool Insert(const K& key, const V& value){if (_root == nullptr){_root = new Node(key, value);return true;}Node* prev = nullptr;Node* cur = _root;while (cur){if (cur->_key > key){prev = cur;cur = cur->_left;}else if (cur->_key < key){prev = cur;cur = cur->_right;}else{return false;}}Node* newnode = new Node(key,value);if (prev->_key > key){prev->_left = newnode;}else if (prev->_key < key){prev->_right = newnode;}return true;}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return cur;}}}bool Erase(const K& key){Node* prev = nullptr;Node* cur = _root;while (cur){if (cur->_key > key){prev = cur;cur = cur->_left;}else if(cur->_key<key){prev = cur;cur = cur->_right;}else{if (cur->_left == nullptr){if (cur == _root){cur = cur->_right;}else {if (cur == prev->_left){prev->_left = cur->_right;}else{prev->_right = cur->_right;}}delete cur;return true;}else if (cur->_right == nullptr){if (cur == _root){cur = cur->_left;}else{if (cur == prev->_left){prev->_left = cur->_left;}else{prev->_right = cur->_left;}}delete cur;return true;}else{Node* RightMinParent = cur;Node* RightMin = cur->_right;while (RightMin->_left){RightMinParent = RightMin;RightMin = RightMin->_left;}cur->_key = RightMin->_key;if (RightMin == RightMinParent->_left){RightMinParent->_left = RightMin->_right;}else{RightMinParent->_right = RightMin->_right;}delete RightMin;return true;}}}return false;}void Inoder(){inoderprint(_root);cout << endl;}void inoderprint( Node* root){if (root == nullptr){return;}inoderprint(root->_left);cout << root->_key << " " << root->_value << endl;inoderprint(root->_right);}private:Node* _root = nullptr;};}

以上实现是 KV模型:

可以使用以下代码测试功能:

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"BSTree.h"int main()
{key_value::BSTree<string, int> BST;BST.Insert("苹果",12);BST.Insert("梨",10);BST.Insert("草莓",9);BST.Insert("橘子",11);BST.Inoder();BST.Erase("梨");BST.Inoder();key_value::BSTreeNode<string,int> *node=BST.Find("苹果");cout << node->_key << " " << node->_value << endl;return 0;
}

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

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

相关文章

JVM内存回收算法

1.1 引用计数法 每个对象创建的时候&#xff0c;会分配一个引用计数器&#xff0c;当这个对象被引用的时候计数器就加1&#xff0c;当不被引用或者引用失效的时候计数器就会减1。任何时候&#xff0c;对象的引用计数器值为0就说明这个对象不被使用了&#xff0c;就认为是“垃圾…

【python】json转成成yaml中文编码异常显示成:\u5317\u4EAC\u8DEF123\u53F7

姊妹篇&#xff1a;【python】json转成成yaml json数据 {"name": "张三","age": 30,"isMarried": false,"children": [{"name": "小王","age": 5},{"name": "小李",&qu…

2024/2/17打卡DFS---经典n—皇后问题***

注意点&#xff1a; 斜线上不能存放多个皇后&#xff0c;可以用截距表示&#xff0c;因为所有的直线斜率都为-1或者 1 &#xff0c;不会存在截距相同的直线。 截距为负数的直线&#xff0c;可以用nabs(截距&#xff09;处理。 另一种处理截距的方式&#xff1a;&#xff08;更…

flutter旋转动画,Android彻底组件化方案实践方法

Android基础 & 常用 针对Android基础&常用知识&#xff0c;我认为对于初级开发者来说&#xff0c;按照优先级最主要的知识点主要包括&#xff1a;四大组件、布局使用、多线程 & 动画&#xff1b;具体介绍如下&#xff1a; 2. Android进阶 针对Android进阶知识&am…

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

Northwestern University-844计算机科学与技术/软件工程-复试注意事项【考研复习】

本文提到的西北大学是位于密歇根湖泊畔的西北大学。西北大学&#xff08;英语&#xff1a;Northwestern University&#xff0c;简称&#xff1a;NU&#xff09;是美国的一所著名私立研究型大学。它由九人于1851年创立&#xff0c;目标是建立一所为西北领地地区的人服务的大学。…

Opencv基础与学习路线

Opencv Opencv每一篇目具体&#xff1a; Opencv(1)读取与图像操作 Opencv(2)绘图与图像操作 Opencv(3)详解霍夫变换 Opencv(4)详解轮廓 Opencv(5)平滑处理 具体Opencv相关demo代码欢迎访问我的github仓库&#xff08;包含python和c代码&#xff09; demo代码 文章目录 Opencv一…

vivo 在离线混部探索与实践

作者&#xff1a;来自 vivo 互联网服务器团队 本文根据甘青、黄荣杰老师在“2023 vivo开发者大会"现场演讲内容整理而成。 伴随 vivo 互联网业务的高速发展&#xff0c;数据中心的规模不断扩大&#xff0c;成本问题日益突出。在离线混部技术可以在保证服务质量的同时&…

Golang 开发实战day01 - Variable String Numeric

Golang 教程01 - Variable String Numeric 1. Go语言的重要性 Go语言&#xff0c;又称Golang&#xff0c;是一种由Google开发的静态编译型编程语言。它于2009年首次发布&#xff0c;并在短短几年内迅速流行起来。Go语言具有以下特点&#xff1a; 语法简单易学&#xff1a;Go…

一线互联网架构师筑基必备技能之Android篇,快速从入门到精通

真正最能锻炼能力的便是直接去阅读源码&#xff0c;不仅限于阅读Android系统源码&#xff0c;还包括各种优秀的开源库。 由于整个文档比较全面&#xff0c;内容比较多&#xff0c;篇幅不允许&#xff0c;下面以截图方式展示 。 深入解析微信 MMKV 源码 初始化获取修改删除读取…

云计算 2月21号 (linux文件及用户管理)

一、文件管理 1.1快捷键 编辑命令&#xff1a; Ctrl a &#xff1a;移到命令行首 Ctrl e &#xff1a;移到命令行尾 Ctrl u &#xff1a;从光标处删除至命令行首 Ctrl k &#xff1a;从光标处删除至命令行尾 Ctrl w &#xff1a;从光标处删除至字首 Ctrl d &#x…

Linux系统中安装redis+redis后台启动+常见相关配置

1、下载Redis Redis官网&#xff1a;https://redis.io/ 历史版本&#xff1a; http://download.redis.io/releases 2、连接Linux&#xff08;或者VMwear&#xff09; 我们安装的是linux版本的redis 打开xftp我们需要先将我们的Redis上传到服务器上 解压到这里 解压的指令 …