【C++】二叉搜索树的模拟实现(K,KV树)递归与非递归方式

文章目录

  • 前言
  • 一、K树
    • 1.结点的定义
    • 2.构造函数
    • 3.拷贝构造函数
    • 4.赋值运算符重载
    • 5.析构函数
    • 6.二叉搜索树的查找(find)
      • 1.非递归
      • 2.递归
    • 7.二叉搜索树的插入(Insert)
      • 1.非递归
      • 2.递归
    • 8.二叉搜素树的删除(Erase)
      • 1.非递归
      • 2.递归
    • 9.中序遍历(InOrder)
  • 二、KV树
  • 二叉搜索树性能


前言

在这里插入图片描述

一、K树

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

1.结点的定义

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

2.构造函数

template<class K>
class BSTree {typedef BSTreeNode<K> Node;
public:BSTree() {_root = nullptr;}

3.拷贝构造函数

BSTree(const BSTree<K>& t) {_root = Copy(t._root);}
Node* Copy(Node* root) {if (root == nullptr) {return nullptr;}//递归进行拷贝Node* copyroot = new Node(root->_key);copyroot->_left = Copy(root->_left);copyroot->_right = Copy(root->_right);return copyroot;}

4.赋值运算符重载

BSTree<K>& operator=(BSTree<K> t) {
//先拷贝出t,让_root指向t的位置,进行交换
//后续调用析构函数直接析构t._rootswap(_root, t._root);return *this;}

5.析构函数

~BSTree() {Destroy(_root);}void Destroy(Node*& root) {if (root == nullptr) {return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}

6.二叉搜索树的查找(find)

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

1.非递归

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

2.递归

bool _FindR(Node*root,const K& key) {if (root == nullptr) {//说明已经找完没找到return false;}if (root->_key < key) {return _FindR(root->_right, key);}else if (root->_key > key) {return _FindR(root->_left, key);}else {return true;}}

7.二叉搜索树的插入(Insert)

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

1.非递归

bool Insert(const K& key) {if (_root == nullptr) {_root = new Node(key);//树为空先建立结点return true;}Node* cur = _root;Node* parent = nullptr;while (cur) {//寻找要插入位置if (cur->_key < key) {parent = cur;cur = cur->_right;}else if (cur->_key > key) {parent = cur;cur = cur->_left;}else {//树中已经有key值不能再插入return false;}}cur = new Node(key);//cur为要插入结点if (parent->_key < key) {//判断cur插在父结点的左数还是右树parent->_right = cur;}else {parent->_left = cur;}return true;//插入成功}

2.递归

在这里插入图片描述

bool InsertR(const K&key) {return _InsertR(_root, key);}bool _InsertR(Node*& root, const K& key) {//这里为结点指针的引用,可以不需要父结点直接修改if (root == nullptr) {root = new Node(key);return true;}if (root->_key < key) {return 	_InsertR(root->_right, key);}else if (root->_key > key) {return _InsertR(root->_left, key);}else {return false;}}

8.二叉搜素树的删除(Erase)

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除

在这里插入图片描述

在这里插入图片描述

1.非递归

	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 {//找到要删除结点//1.   要删除节点左边为空if (cur->_left == nullptr) {if (cur == _root) {//要删除结点为根节点,则改变根节点位置_root = _root->_right;}else {//判断要删除结点在父结点的左子树还是右子树if (parent->_right == cur) {//在父结点右子树则让其指向删除结点的右子树parent->_right = cur->_right;}else {parent->_left = cur->_right;}}}//2.     要删除节点右边为空else if (cur->_right == nullptr) {if (cur == _root) {//要删除结点为根节点,则改变根节点位置_root = _root->_left;}else {//判断要删除结点在父结点的左子树还是右子树if (parent->_right == cur) {parent->_right = cur->_left;}else {parent->_left = cur->_left;}}}else {//3.要删除结点左右子树都不为空Node* parent = cur;Node* leftMax = cur->_left;//寻找可替代结点,替代过好要满足二叉搜索树的性质//要删除结点左子树的最大值,或者右子树的最小值while (leftMax->_right) {//寻找左子树的最大值parent = leftMax;leftMax = leftMax->_right;}swap(leftMax->_key, cur->_key);//替代结点与被删除结点的值交换//这样leftMax就为要被删除的结点if (parent->_left == leftMax) {//判断leftMax在父结点的左子树还是右子树parent->_left = leftMax->_left;}else {parent->_right = leftMax->_left;}//改变指向cur = leftMax;}delete cur;return true;}	}return false;}

2.递归

bool EraseR(const K&key) {return _EraseR(_root, key);}bool _EraseR(Node*& root, const K& key) {//这里为结点指针的引用,可以不需要父结点直接修改if (root == nullptr) {return false;}if (root->_key < key) {return _Erase(root->_right, key);}else if (root->_key > key) {return _Erase(root->_left, key);}//寻找要删除结点else {Node* del = root;//1. 要删除节点左边为空if (root->_left == nullptr) {root = root->_right;}//2. 要删除节点右边为空else if (root->_right == nullptr) {root = root->_left;}else {//3.要删除结点左右都不为空Node* leftMax = root->_left;while (leftMax->_right) {//寻找替代结点leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);//交换值后,要删除的结点为leftMax,其在root的左子树return _Erase(root->_left, key);}delete del;return true;}}

9.中序遍历(InOrder)

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

二、KV树

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

namespace key_value {template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _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:BSTree() {_root = nullptr;}BSTree(const BSTree<K, V>& t) {_root = Copy(t._root);}BSTree<K, V>& operator=(BSTree<K, V> t) {swap(_root, t._root);return *this;}~BSTree() {Destroy(_root);}bool InsertR(const K& key, const V& value) {return _InsertR(_root, key, value);}bool EraseR(const K& key) {return _Erase(_root, key);}Node* FindR(const K& key) {return 	_FindR(_root, key);}void InOrder() {_InOrder(_root);cout << endl;}private:Node* Copy(Node* root) {if (root == nullptr) {return nullptr;}Node* copyroot = new Node(root->_key);copyroot->_left = Copy(root->_left);copyroot->_right = Copy(root->_right);return copyroot;}void Destroy(Node*& root) {if (root == nullptr) {return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}Node* _FindR(Node* root, const K& key) {if (root == nullptr) {return nullptr;}if (root->_key < key) {return _FindR(root->_right, key);}else if (root->_key > key) {return _FindR(root->_left, key);}else {return root;}}bool _InsertR(Node*& root, const K& key, const V& value) {if (root == nullptr) {root = new Node(key, value);return true;}if (root->_key < key) {return _InsertR(root->_right, key, value);}else if (root->_key > key) {return _InsertR(root->_left, key, value);}else {return false;}}bool _Erase(Node*& root, const K& key) {if (root == nullptr) {return false;}if (root->_key < key) {return _Erase(root->_right, key);}else if (root->_key > 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* leftMax = root->_left;while (leftMax->_right) {leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _Erase(root->_left, key);}delete del;return true;}}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root;};
}

二叉搜索树性能

在这里插入图片描述

最高找高度次O(N)

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

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

相关文章

yolov5的报错

【定期水一期】 &#xff08;这个问题很抓马&#xff0c;可以看一下这篇文章&#xff1a;Git Bash 教程&#xff01;【不是所有人都会用Git】&#xff09; 一&#xff1a;没有cv2这个模块 解决方案&#xff1a; pip install opencv-python -i http://pypi.douban.com/simple/…

emqx-5.1.4开源版使用记录

emqx-5.1.4开源版使用记录 windows系统安装eqmx 去官网下载 emqx-5.1.4-windows-amd64.zip&#xff0c;然后找个目录解压 进入bin目录,执行命令启动emqx 执行命令 emqx.cmd start使用emqx 访问内置的web管理页面 浏览器访问地址 http://localhost:18083/#/dashboard/overv…

Git和GitHub

文章目录 1.Git介绍2. 常用命令3. Git分支操作4. Git团队协作机制5. GitHub操作6. IDEA集成Git7.IDEA操作GitHub8. Gitee 1.Git介绍 Git免费的开源的分布式版本控制系统&#xff0c;可以快速高效从小到大的各种项目 Git易于学习&#xff0c;占地面积小&#xff0c;性能快。它…

企业权限管理(七)-权限操作

1. 数据库与表结构 1.1 用户表 1.1.1 用户表信息描述 users 1.1.2 sql语句 CREATE TABLE users( id varchar2(32) default SYS_GUID() PRIMARY KEY, email VARCHAR2(50) UNIQUE NOT NULL, username VARCHAR2(50), PASSWORD VARCHAR2(50), phoneNum VARCHAR2(20), STATUS INT )…

SolidWorks二次开发系列入门100篇之98、99-分割、保存零件中的实体

从这四张图&#xff0c;看了来这个保存实体和分割图标是一样的&#xff0c;可能只是选项不一样&#xff0c;所以这里一起写了&#xff0c;不浪费时间。 经过了几个小时的研究&#xff0c;没搞定。大哭 CreateSaveBodyFeature这个没有api例子&#xff0c;2021上有例子&#xff…

使用Java根据表名导出与导入Sql

前言 很粗糙啊&#xff0c;有很多可以优化的地方&#xff0c;而且也不安全&#xff0c;但是临时用还是OK的&#xff0c;我这个是公司里面的单机软件&#xff0c;不联网。 嗨&#xff01;我是一名社交媒体增长黑客&#xff0c;很高兴能帮助您优化和丰富关于批量作业导出和导入…

nginx文件共享、服务状态和location模块的配置介绍

一.文件共享功能 1.清空html目录下文件并新建你要共享的文件 2.修改nginx.conf文件&#xff0c;开启autoindex功能 3.测试 二.状态模块 1.修改nginx.conf文件 2.测试 &#xff08;1&#xff09;使用刚才定义的IP/nginx_status进行访问 &#xff08;2&#xff09;status参…

贝锐蒲公英:快速搭建连锁门店监控体系,赋能企业高效管理

随着国民生活水平的提高和零售场景的变革&#xff0c;消费者对于餐饮类目的消费支出不断增加&#xff0c;线下社区生鲜商超作为下沉市场最主要的消费场景之一&#xff0c;蕴藏着巨大价值机会。 对于线下连锁生鲜超市而言&#xff0c;连锁门店多、员工多&#xff0c;门店管理时会…

FreeRTOS( 任务与中断优先级,临界保护)

资料来源于硬件家园&#xff1a;资料汇总 - FreeRTOS实时操作系统课程(多任务管理) 目录 一、中断优先级 1、NVIC基础知识 2、FreeRTOS配置NVIC 3、SVC、PendSV、Systick中断 4、不受FreeRTOS管理的中断 5、STM32CubeMX配置 二、任务优先级 1、任务优先级说明 2、任务…

数据结构笔记--链表经典高频题

目录 前言 1--反转单向链表 2--反转单向链表-II 3--反转双向链表 4--打印两个有序链表的公共部分 5--回文链表 6--链表调整 7--复制含有随机指针结点的链表 8--两个单链表相交问题 前言 面经&#xff1a; 针对链表的题目&#xff0c;对于笔试可以不太在乎空间复杂度&a…

SD-MTSP:蜘蛛蜂优化算法SWO求解单仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&#xff0c;具有搜索速度快&#xff0c;求解精度高的优势。蜘蛛蜂优化算…

Spring Gateway+Security+OAuth2+RBAC 实现SSO统一认证平台

背景&#xff1a;新项目准备用SSO来整合之前多个项目的登录和权限&#xff0c;同时引入网关来做后续的服务限流之类的操作&#xff0c;所以搭建了下面这个系统雏形。 关键词&#xff1a;Spring Gateway, Spring Security, JWT, OAuth2, Nacos, Redis, Danymic datasource, Jav…

竞赛项目 深度学习的口罩佩戴检测 - opencv 卷积神经网络 机器视觉 深度学习

文章目录 0 简介1 课题背景&#x1f6a9; 2 口罩佩戴算法实现2.1 YOLO 模型概览2.2 YOLOv32.3 YOLO 口罩佩戴检测实现数据集 2.4 实现代码2.5 检测效果 3 口罩佩戴检测算法评价指标3.1 准确率&#xff08;Accuracy&#xff09;3.2 精确率(Precision)和召回率(Recall)3.3 平均精…

ASP.NET Core中间件记录管道图和内置中间件

管道记录 下图显示了 ASP.NET Core MVC 和 Razor Pages 应用程序的完整请求处理管道 中间件组件在文件中添加的顺序Program.cs定义了请求时调用中间件组件的顺序以及响应的相反顺序。该顺序对于安全性、性能和功能至关重要。 内置中间件记录 内置中间件原文翻译MiddlewareDe…

【容器化】Oceanbase镜像构建及使用

通过该篇文章可以在国产X86-64或ARM架构上构建商业版oceanbase&#xff0c;只需要替换pkg安装包即可。下面截图主要以国产X86-64安装为例&#xff0c;作为操作截图&#xff1a; 镜像构建目录说明 pkg:用来存放安装包及脚本&#xff0c;抛出rpm其他是脚步&#xff0c;这些rpm包…

直接在html中引入Vue.js的cdn来实现Vue3的组合式API

Vue3的组合式API是使用setup函数来编写组件逻辑的。setup函数是Vue3中用于替代Vue2的选项API&#xff08;如data、methods等&#xff09;的一种方式。在setup函数中&#xff0c;你可以访问到一些特殊的响应式对象&#xff0c;并且可以返回一些可以在模板中使用的数据、方法等。…

Python编程——谈谈函数的定义、调用与传入参数

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 一、理解函数 二、函数的定义 1、语法 2、定义一个…

【Linux】内核宏定义解释postcore_initcall,arch_initcall,subsys_initcall

postcore_initcall postcore_initcall(pcibus_class_init) 是一个宏&#xff0c;用于在Linux内核初始化过程中注册一个后期初始化函数。 这个宏的含义如下&#xff1a; postcore_initcall 是一个宏定义&#xff0c;用于指定注册的函数在内核初始化的哪个阶段执行。 pcibus_cl…

deleteDatabase失败处理

准备清理环境时发现deleteDatabase告警&#xff0c;如下图 SYSorcl> startup; ORACLE instance started. Total System Global Area 1.6106E10 bytes Fixed Size 8639712 bytes Variable Size 2449476384 bytes Datab…

CentOS-6.3安装MySQL集群

安装要求 安装环境&#xff1a;CentOS-6.3 安装方式&#xff1a;源码编译安装 软件名称&#xff1a;mysql-cluster-gpl-7.2.6-linux2.6-x86_64.tar.gz 下载地址&#xff1a;http://mysql.mirror.kangaroot.net/Downloads/ 软件安装位置&#xff1a;/usr/local/mysql 数据存放位…