【C++ 二叉搜索树】

目录

  • 1.什么是二叉搜索树
  • 2.构建二叉搜索树
    • 2.1首先搭建树的框架
    • 2.2搭建搜索树的框架
  • 3.二叉搜索树的插入
    • 3.1非递归式插入
    • 3.2递归式插入
  • 4.二叉搜索树的查找
    • 4.1非递归查找
    • 4.2递归查找
  • 5.二叉搜索树的删除
    • 5.1非递归删除
    • 5.2递归删除
  • 6.整个代码实现

1.什么是二叉搜索树

简单来讲就是一个树的左子树的值都小于根,右子树的值都大于根。如:
在这里插入图片描述
这个树的特点是走一趟中序就完成了对一组树的排序。查找一个树也特别的方便,最多只需要走树的高度次。所以当这个树比较饱满时搜索的效率很高,所以被称为二叉搜索树。

2.构建二叉搜索树

2.1首先搭建树的框架

struct TreeNode
{TreeNode<V>* _left;TreeNode<V>* _right;V _val;//构造函数TreeNode(V val){_left = nullptr;_right = nullptr;_val = val;}
};

2.2搭建搜索树的框架

template<class V>
class BSTree
{typedef TreeNode<V> Node;
public:BSTree(){_head = nullptr;}private:Node* _head;};

3.二叉搜索树的插入

3.1非递归式插入

1.思路
在这里插入图片描述
2.代码

//插入(非递归)bool insert(V val){if (_head == nullptr){_head = new Node(val);return true;}//找到要插入结点的位置Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val < val){parent = cur;cur = cur->_right;}else if (cur->_val > val){parent = cur;cur = cur->_left;}else{//相等  返回falsereturn false;}}//判断val插在parent的左还是右if (parent->_val >val){parent->_left = new Node(val);return true;}else{parent->_right = new Node(val);return true;}

3.2递归式插入

	bool insertR(V val){return _insertR(_head, val);}bool _insertR(Node*& head, V val){if (head == nullptr){head = new Node(val);return true;}if (head->_val > val){_insertR(head->_left,val);}else if (head->_val < val){_insertR(head->_right, val);}else{return false;}return false;}

注意点:这个递归式插入其实也没什么难的,就是有个注意点是要引用传参。如果不是引用传参是不会修改-head的。

4.二叉搜索树的查找

4.1非递归查找

//非递归查找
bool find(V val)
{if (_head == nullptr){return false;}Node* cur = _head;while (cur){if (cur->_val < val){cur = cur->_right;}else if (cur->_val > val){cur = cur->_left;}else{return true;}}
}

4.2递归查找

bool findR(const V& val)
{return _findR(_head, val);
}bool _findR(Node* head, const V& val)
{if (head == nullptr){return false;}if (head->_val == val){return true;}return _findR(head->_left, val) || _findR(head->_right, val);
}

比较常规,没什么要解释的。

5.二叉搜索树的删除

5.1非递归删除

算法思路:
在这里插入图片描述

代码实现:

//非递归式删除
bool erase(const V& val)
{//第一步找到要删除的结点Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val > val){parent = cur;cur = cur->_left;}else if (cur->_val < val){parent = cur;cur = cur->_right;}else{//找到了//分情况讨论if (cur->_left == nullptr){//特殊情况if (cur == _head){_head = _head->_right;return true;}if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr){//特殊情况if (cur == _head){_head = _head->_left;return true;}if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;return true;}else{//找LeftMaxNode* parent = cur;Node* LeftMax = cur->_left;while (LeftMax->_right){parent = LeftMax;LeftMax = LeftMax->_right;}//交换cur与LeftMax的valswap(cur->_val, LeftMax->_val);if (parent->_left == LeftMax){parent->_left = LeftMax->_right;}else{parent->_right = LeftMax->_right;}delete LeftMax;return true;}}}return false;
}

注:这个非递归主要就是要完全考虑到删除结点会出现的可能,代码实现不复杂,但是很难一起写对,写错了调试也好很久(本人亲身经历调试了一个下午)。

5.2递归删除

算法思路:
在这里插入图片描述

代码实现:

bool _eraseR(Node*& head, const V& val){if (head == nullptr){return false;}else if (head->_val > val){_eraseR(head->_left, val);}else if (head->_val < val){_eraseR(head->_right, val);}else{//递归找到了Node* del = head;//三种情况//1.左子树为空if (head->_left == nullptr){head = head->_right;}//2.右子树为空else if(head->_right == nullptr){head = head->_left;}//3.左右子树都不为空else{//找LeftMaxNode* LeftMax = head->_left;while (LeftMax->_right){LeftMax = LeftMax->_right;}//交换swap(head->_val, LeftMax->_val);//递归删除return _eraseR(head->_left, val);}delete del;return true;}}

6.整个代码实现

#pragma once
template<class V>
struct TreeNode
{TreeNode<V>* _left;TreeNode<V>* _right;V _val;//构造函数TreeNode(V val){_left = nullptr;_right = nullptr;_val = val;}
};template<class V>
class BSTree
{typedef TreeNode<V> Node;
public:BSTree(){_head = nullptr;}//深拷贝BSTree(BSTree<V>& bs){_head = CopyTree(bs._head);}//赋值BSTree<V>& operator=(BSTree<V> bs){swap(_head, bs._head);return *this;}//插入(非递归)bool insert(V val){if (_head == nullptr){_head = new Node(val);return true;}//找到要插入结点的位置Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val < val){parent = cur;cur = cur->_right;}else if (cur->_val > val){parent = cur;cur = cur->_left;}else{//相等  返回falsereturn false;}}//判断val插在parent的左还是右if (parent->_val >val){parent->_left = new Node(val);return true;}else{parent->_right = new Node(val);return true;}}bool insertR(V val){return _insertR(_head, val);}//非递归查找bool find(V val){if (_head == nullptr){return false;}Node* cur = _head;while (cur){if (cur->_val < val){cur = cur->_right;}else if (cur->_val > val){cur = cur->_left;}else{return true;}}}bool findR(const V& val){return _findR(_head, val);}~BSTree(){destory(_head);}void inorder(){_inorder(_head);cout << endl;}//非递归式删除bool erase(const V& val){//第一步找到要删除的结点Node* parent = _head;Node* cur = _head;while (cur){if (cur->_val > val){parent = cur;cur = cur->_left;}else if (cur->_val < val){parent = cur;cur = cur->_right;}else{//找到了//分情况讨论if (cur->_left == nullptr){//特殊情况if (cur == _head){_head = _head->_right;return true;}if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr){//特殊情况if (cur == _head){_head = _head->_left;return true;}if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;return true;}else{//找LeftMaxNode* parent = cur;Node* LeftMax = cur->_left;while (LeftMax->_right){parent = LeftMax;LeftMax = LeftMax->_right;}//交换cur与LeftMax的valswap(cur->_val, LeftMax->_val);if (parent->_left == LeftMax){parent->_left = LeftMax->_right;}else{parent->_right = LeftMax->_right;}delete LeftMax;return true;}}}return false;}bool eraseR(const V& val){return _eraseR(_head, val);}private:Node* _head;void destory(Node*& head){if (head == nullptr){return;}destory(head->_left);destory(head->_right);delete head;head = nullptr;}bool _insertR(Node*& head, V val){if (head == nullptr){head = new Node(val);return true;}if (head->_val > val){_insertR(head->_left,val);}else if (head->_val < val){_insertR(head->_right, val);}else{return false;}return false;}void _inorder(Node* head){if (head == nullptr){return;}_inorder(head->_left);cout << head->_val << " ";_inorder(head->_right);}bool _findR(Node* head, const V& val){if (head == nullptr){return false;}if (head->_val == val){return true;}return _findR(head->_left, val) || _findR(head->_right, val);}bool _eraseR(Node*& head, const V& val){if (head == nullptr){return false;}else if (head->_val > val){_eraseR(head->_left, val);}else if (head->_val < val){_eraseR(head->_right, val);}else{//递归找到了Node* del = head;//三种情况//1.左子树为空if (head->_left == nullptr){head = head->_right;}//2.右子树为空else if(head->_right == nullptr){head = head->_left;}//3.左右子树都不为空else{//找LeftMaxNode* LeftMax = head->_left;while (LeftMax->_right){LeftMax = LeftMax->_right;}//交换swap(head->_val, LeftMax->_val);//递归删除return _eraseR(head->_left, val);}delete del;return true;}}Node* CopyTree(Node* head){if (head == nullptr){return nullptr;}Node* newhead = new Node(head->_val);newhead->_left = CopyTree(head->_left);newhead->_right = CopyTree(head->_right);return newhead;}};

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

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

相关文章

NSSCTF web 刷题记录1

文章目录 前言题目[GXYCTF 2019]禁止套娃方法一方法二 [NCTF 2019]Fake XML cookbook[NSSRound#7 Team]ec_RCE[NCTF 2018]Flask PLUS 前言 今天是2023.9.3&#xff0c;大二开学前的最后一天。老实说ctf的功力还是不太够做的题目太少&#xff0c;新学期新气象。不可急于求成&am…

设置 Hue Server 与 Hue Web 界面之间的会话超时时间

设置 Hue Server 与 Hue Web 界面之间的会话超时时间 在 CDH 的 Hue 中&#xff0c;Auto Logout Timeout 参数表示用户在不活动一段时间后将自动注销&#xff08;登出&#xff09;的超时时间。当用户在 Hue 中处于不活动状态超过该设定时间时&#xff0c;系统将自动注销用户&am…

FreeRTOS中断与任务之间同步(Error:..\..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,422 )

前言&#xff1a; FreeRTOS中&#xff0c;中断需要注意几点&#xff1a; 何时使用中断&#xff1b;中断服务函数&#xff08;ISR&#xff09;要处理的数据量有多大&#xff0c;通常我们希望中断的切换越快越好&#xff0c;也就是说&#xff0c;ISR尽量采用耗时较少的处理方式…

撮合前端平台在低代码平台的落地实践 | 京东云技术团队

在京东技术的发展当下&#xff0c;不同的业务线&#xff0c;不同的区域&#xff0c;甚至于很多触达消费者的端&#xff0c;正在被中台架构能力所支撑。大家都很清楚&#xff0c;中台建设能够带来技术的规模化效应&#xff0c;具有提高业务协同、加速创新和交付速度、提高系统稳…

Java问题诊断和排查工具

文章目录 一、前言二、Java问题诊断和排查工具1、JDK自带工具2、常用命令3、JAVA Dump&#xff1a;3.1、jps3.2、jstack3.3、jmap3.3.1、jmap -heap pid:查看堆使用情况3.3.2、jmap -histo pid&#xff1a;查看堆中对象数量和大小3.3.3、jmap -dump:formatb,fileheapdump pid&a…

K8S的介绍和架构

仅供入门 K8S的介绍和架构 一. 什么是kubernetes二、Kubernetes架构和组件 2.1 核心组件 2.1.1 Kubernetes Master控制组件&#xff0c;调度管理整个系统&#xff08;集群&#xff09;&#xff0c;包含如下组件: a、Kubernetes API Serverb、Kubernetes Schedulerc、Kubernet…

springboot自动装配原理,手写一个starter。

文章目录 springboot自动装配原理手写starter手写starter总结&#xff1a; springboot自动装配原理 口述&#xff1a; springboot自动装配的话它其实就是只需要我们添加一个starter起步依赖&#xff0c;它就能完成这个依赖组件相关Bean的自动注入&#xff0c;其实就是自动的将…

SpringMVC的工作流程及入门

目录 一、概述 ( 1 ) 是什么 ( 2 ) 作用 二、工作流程 ( 1 ) 流程 ( 2 ) 步骤 三、入门实例 ( 1 ) 入门实例 ( 2 ) 静态资源处理 给我们带来的收获 一、概述 ( 1 ) 是什么 SpringMVC是一个基于Java的Web应用开发框架&#xff0c;它是Spring Framework的一部…

5.bs4的基本使用

bs4是python的一个第三方库&#xff0c;用来做数据解析的 目录 1 安装bs4 2 解析本地的html文件 3 解析网上的html 4 找到指定的标签 4.1 获取页面中第一个指定标签的内容 4.2 查找页面中的第一个符合要求的内容 BeautifulSoup.find() 4.2.1 标签 4.2.2 类名 …

Linux--进程概念

1.什么是程序&#xff1f;什么是进程&#xff1f;有什么区别&#xff1f; 程序&#xff1a;是静态的概念&#xff0c;gcc xxx.c -o pro 磁盘中生成的pro文件&#xff0c;叫做程序。 进程&#xff1a;是程序的一种与运行活动&#xff0c;通俗的意思是程序跑起来了&#xff0c;系…

linux免密登录最简单--图文详解

最简单的免密登录 1.A电脑生成秘钥 ssh-keygen -t rsa 2.A电脑将秘钥传给B电脑 ssh-copy-id root192.168.1.129 #将秘钥直接传给B电脑 需要输入B电脑的密码&#xff0c;可以看到成功。 3.测试 同理&#xff1a;如果B->A也需要免密登录&#xff0c;统一的操作。 大功告…

PHP8的数组-PHP8知识详解

今天开始学习数组&#xff0c; 本文主要讲了三点&#xff1a;什么是数组、php8中数组的改进、数组函数。 一、什么是数组 在PHP8中&#xff0c;数组是非常重要的数据类型。相对于其他的数据类型&#xff0c;数组更像一种结构&#xff0c;而这种结构可以储存一系列数值。 数组…

【SpringSecurity】八、集成图片验证码

文章目录 1、生成图片验证码2、创建验证码过滤器3、将过滤器加入SpringSecurity过滤链4、修改登录页 SpringSecurity是通过过滤器链来完成的&#xff0c;接下来的验证码&#xff0c;可以尝试创建一个过滤器放到Security的过滤器链中&#xff0c;在自定义的过滤器中比较验证码。…

90、00后严选出的数据可视化工具:奥威BI工具

90、00后主打一个巧用工具&#xff0c;绝不低效率上班&#xff0c;因此当擅长大数据智能可视化分析的BI数据可视化工具出现后&#xff0c;自然而然地就成了90、00后职场人常用的数据可视化工具。 奥威BI工具三大特点&#xff0c;让职场人眼前一亮&#xff01; 1、零编程&…

医学影像工作站PACS系统源码,医院PACS系统源码

医学影像(PACS)系统主要进行病人信息和影像的获取、处理、存储、调阅、检索、管理&#xff0c;并通过网络向全院提供病人检查影像及诊断报告&#xff1b;各影像科室之间共享不同设备的病人检查影像及诊断报告&#xff1b;在诊断工作站上&#xff0c;调阅HIS中病人的其它信息&am…

Android架构 架构和 CPU ABI - NDK

查看设备架构 adb -s emulator-5554 shell getprop ro.product.cpu.abi C:\Users\liyd>adb -s emulator-5554 shell getprop ro.product.cpu.abi x86_64C:\Users\liyd>adb -s 804c11f1 shell getprop ro.product.cpu.abi arm64-v8amumu模拟器12 C:\Users\liyd>adb …

ElasticSearch入门

一、基本命令_cat 1、查看节点信息 http://192.168.101.132:9200/_cat/nodes2、查看健康状况 http://192.168.101.132:9200/_cat/health3、查看主节点的信息 http://192.168.101.132:9200/_cat/master4、查看所有索引 http://192.168.101.132:9200/_cat/indices二、索引一…

【算法与数据结构】700、LeetCode二叉搜索树中的搜索

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;二叉搜索树的性质&#xff1a;左节点键值 < 中间节点键值 < 右节点键值。那么我们根据此性质&am…

2023-09-02 LeetCode每日一题(最多可以摧毁的敌人城堡数目)

2023-09-02每日一题 一、题目编号 2511. 最多可以摧毁的敌人城堡数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 n &#xff0c;下标从 0 开始的整数数组 forts &#xff0c;表示一些城堡。forts[i] 可以是 -1 &#xff0c;0 或者 1 &#xff0c;其中&…

Burp插件HaE与Authz用法

HaE与Authz均为BurpSuite插件生态的一员&#xff0c;两者搭配可以避免“越权”、“未授权”两类漏洞的重复测试行为。&#xff08;适用于业务繁杂&#xff0c;系统模块功能多的场景&#xff09; 两个插件都可以在store里安装 安装完后&#xff0c;点击Filter Settings勾选Sho…