【深入C++】二叉搜索树

news2024/12/27 9:32:33

文章目录

  • 什么是二叉搜索树
  • 二叉搜索树的接口
    • 1.查找操作
    • 2.插入操作
    • 3.中序遍历
    • 4.删除操作
  • 所有代码
  • 总结

在这里插入图片描述

在这里插入图片描述

什么是二叉搜索树

二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树,其每个节点最多有两个子节点,分别称为左子节点和右子节点。BST具有以下性质:

  1. 左子树的所有节点值都小于根节点的值:即对于每一个节点,其左子树上所有节点的值都比该节点的值小。
  2. 右子树的所有节点值都大于根节点的值:即对于每一个节点,其右子树上所有节点的值都比该节点的值大。
  3. 每个子树也是二叉搜索树:这意味着BST的定义在每个节点的子树上都成立。

形如下面这棵树就是一颗二叉搜索树:

       8
     /   \
    3     10
   / \      \
  1   6      14
     / \     /
    4   7   13

二叉搜索树的接口

要写二叉搜索树的接口,我们先得定义一颗二叉搜索树:

定义二叉搜索树的节点:

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

定义二叉搜索树:

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

1.查找操作

由于二叉搜索树的性质,所以这里我们可以直接用while循环来查找,不需要进行递归来查找:

bool Find(const K& key)
{
	Node* cur = _root;
	while (cur)
	{
		//小于当前节点,在左子树
		if (cur->_key > key)cur = cur->_left;
		//大于当前节点,在右子树
		else if (cur->_key < key) cur = cur->_right;
		//等于当前节点,返回true
		else return true;
	}
	return false;
}

2.插入操作

插入操作我们只需要找到插入的位置,然后插入节点即可,如果没有找到,则返回false,如果找到了并成功插入了,则返回true。

bool Insert(const K& key)
{
	//没有根节点的情况
	if (_root == nullptr)
	{
		_root = new Node(key);
		return true;
	}
	//遍历节点
	Node* cur = _root;
	//记录当前节点的父节点
	Node* parent = nullptr;
	while (cur)
	{
		parent = cur;
		if (cur->_key > key)cur = cur->_left;
		else if (cur->_key < key) cur = cur->_right;
		else return false;
	}
	//找到插入的地方,直接new
	cur = new Node(key);
	//判断插入到父节点的左节点还是右节点
	if (parent->_key < key) parent->_right = cur;
	else parent->_left = cur;
	return true;
}

3.中序遍历

对于中序遍历,我们需要写一个辅助函数,来传递当前this指针对应的root。

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

4.删除操作

插入操作分三种情况:
在这里插入图片描述
我们拿下面这个二叉搜索树为例子:
在这里插入图片描述

将节点进行归类:
在这里插入图片描述
我们先讨论删除没有孩子的节点,对于没有孩子的节点我们可以直接进行删除。
其次,我们来讨论删除一个孩子的节点,假如我们删除14,我们需要知道14的父亲,将10和14的左孩子串起来。
在这里插入图片描述
可以将一个孩子的节点归结为这几种情况。
接下来就是有两个孩子的节点:
在这里插入图片描述
我们拿3这个节点为例子:
在这里插入图片描述

删除3节点,我们应该用左子树最大,或者右子树最小进行替换,然后转化成删除左子树最大,或者右子树最小的节点,就相当于把删除有两个孩子的节点转换成删除一个孩子的节点或者没有孩子的节点。

bool Erase(const K& key)
{
	//三种情况:
	//1.一个孩子
	//2.没有孩子
	//3.两个孩子:左子树的最大,右子树的最小
	//左子树的最左,右子树的最右
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (cur->_key < key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else
		{
			//删除
			//0-1个孩子的情况
			if (cur->_left == nullptr)
			{
				//删除根节点的情况
				if (parent == nullptr)_root = cur->_right;
				else
				{
					if (parent->_left == cur) parent->_left = cur->_right;
					else parent->_right = cur->_right;
				}
				delete cur;
				return true;
			}
			else if (cur->_right == nullptr)
			{
				//删除根节点
				if (parent == nullptr) _root = cur->_left;
				else
				{
					if (parent->_left == cur)parent->_left = cur->_left;
					else parent->_left = cur->_left;
				}
				delete cur;
				return true;
			}
			//两个孩子的情况
			else
			{
				//找右子树最小的节点作为最大的节点
				Node* rightminp = nullptr;
				Node* rightmin = cur->_right;
				//left不为空就一直向left走
				while (rightmin->_left != nullptr)
				{
					rightminp = rightmin;
					rightmin = rightmin->_left;
				}
				cur->_key = rightmin->_key;
				if (rightminp != nullptr) rightminp->_left = rightmin->_right;
				else cur->_right = rightmin->_right;
				delete rightmin;
				return true;
			}

		}
	}
	return false;
}

删除成功返回true,删除失败没找到则返回false。

所有代码

#pragma once
#include<iostream>
using namespace std;
template<class K>
struct BSTreeNode
{
	K _key;
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;
	BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){}
};

template<class K>
class BSTree
{
	typedef BSTreeNode<K> Node;
public:
	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			if (cur->_key > key)cur = cur->_left;
			else if (cur->_key < key) cur = cur->_right;
			else return false;
		}
		cur = new Node(key);
		if (parent->_key < key) parent->_right = cur;
		else parent->_left = cur;
		return true;
	}
	bool 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 true;
		}
		return false;
	}

	bool Erase(const K& key)
	{
		//三种情况:
		//1.一个孩子
		//2.没有孩子
		//3.两个孩子:左子树的最大,右子树的最小
		//左子树的最左,右子树的最右
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//删除
				//0-1个孩子的情况
				if (cur->_left == nullptr)
				{
					//删除根节点的情况
					if (parent == nullptr)_root = cur->_right;
					else
					{
						if (parent->_left == cur) parent->_left = cur->_right;
						else parent->_right = cur->_right;
					}
					delete cur;
					return true;
				}
				else if (cur->_right == nullptr)
				{
					//删除根节点
					if (parent == nullptr) _root = cur->_left;
					else
					{
						if (parent->_left == cur)parent->_left = cur->_left;
						else parent->_left = cur->_left;
					}
					delete cur;
					return true;
				}
				//两个孩子的情况
				else
				{
					//找右子树最小的节点作为最大的节点
					Node* rightminp = nullptr;
					Node* rightmin = cur->_right;
					//left不为空就一直向left走
					while (rightmin->_left != nullptr)
					{
						rightminp = rightmin;
						rightmin = rightmin->_left;
					}
					cur->_key = rightmin->_key;
					if (rightminp != nullptr) rightminp->_left = rightmin->_right;
					else cur->_right = rightmin->_right;
					delete rightmin;
					return true;
				}

			}
		}
		return false;
	}
	void InOrder()
	{
		_InOrder(_root);
	}
private:
	void _InOrder(Node* root)
	{
		if (root == nullptr) return;
		_InOrder(root->_left);
		cout << root->_key << ' ';
		_InOrder(root->_right);
	}
	Node* _root = nullptr;
};

总结

二叉搜索树(BST)是一种在计算机科学中广泛应用的数据结构,具有高效的查找、插入和删除操作。通过遵循节点值的有序性规则,BST能够在平均情况下实现对数时间复杂度的操作,使其成为处理动态数据集的理想选择。

在本篇博客中,我们详细介绍了二叉搜索树的定义和性质,并通过示例展示了其基本结构。我们还探讨了BST的三大主要操作:插入、查找和删除,并分析了这些操作的实现方法和时间复杂度。

尽管二叉搜索树在平衡状态下具有高效的性能,但在最坏情况下,BST可能会退化成链表。因此,在实际应用中,经常需要采用自平衡二叉搜索树(如AVL树和红黑树)来保证其性能。

通过对BST的深入理解和实践,相信你能够在各种编程场景中灵活运用这一重要的数据结构,从而提高程序的效率和性能。如果你对二叉搜索树有任何疑问或希望了解更多高级应用,欢迎在评论区留言讨论。

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

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

相关文章

MySQL 数据库 day 7.16

ok了家人们今天继续记录一下数据库,看看今天学了什么。 一.事物概述 1.1 环境准备 -- 账户表 create table account( id int primary key auto_increment, name varchar(20), money double );insert into account values (null,张三,1000); insert into account values (n…

Matlab Git管理

目录 1、Git配置 1.1 下载 1.2 注册账户 1.3 录入信息 2、matlab配置 2.1 测试git 2.2 创建git 1、Git配置 1.1 下载 使用镜像网站&#xff0c;选择合适的版本download git&#xff0c;一直点next&#xff0c;最后install。 CNPM Binaries Mirror (npmmirror.co…

区块链技术在智能家居中的创新应用探索

随着物联网技术的发展和智能家居市场的蓬勃发展&#xff0c;区块链技术作为一种去中心化的数据管理和安全保障技术&#xff0c;正在逐渐引入智能家居领域&#xff0c;并为其带来了新的创新应用。本文将探讨区块链技术在智能家居中的具体应用场景、优势以及未来发展方向。 智能家…

[MMU]现代计算机内存管理

现代计算机内存管理 内存管理 内存分配与回收 逻辑上对内存空间进行扩充 覆盖技术程序内存区域分为一个固定区和若干个覆盖区 将程序分为多个段&#xff0c;常用的段常驻内存放在固定区、不常用的在需要的时候调入覆盖区 必须由程序员声明覆盖结构 交换技术 虚拟内存 逻辑地址…

《JavaSE》------20.语法实践项目【图书管理系统】

目录 前言 一、图书管理系统成果展示 1.1 管理员&#xff1a; 1.2 普通用户&#xff1a; 二、 图书管理系统框架的搭建 2.1 book包 2.1.2 BookList类 2.2 operation包 2.2.0 IOperation接口 2.2.1 AddOperatoon类 2.2.2 FindOperation类 2.2.3 DelOperation类 2.2…

昇思MindSpore 应用学习-Vision Transformer图像分类

昇思MindSpore 应用学习-Vision Transformer图像分类(AI 代码解析) Vision Transformer图像分类 Vision Transformer&#xff08;ViT&#xff09;简介 近些年&#xff0c;随着基于自注意&#xff08;Self-Attention&#xff09;结构的模型的发展&#xff0c;特别是Transform…

渗透测试靶机---Kioptrix5

渗透测试靶机—Kioptrix5 启动靶机&#xff0c;扫描ip&#xff0c;平平无奇 扫描 惯例&#xff0c;访问80&#xff0c;先看看 好像是没什么内容&#xff0c;查看页面源代码 搜素这个页面的框架&#xff1a; 直接拉下来查看就行 这里存在一个路径穿越 这里就暴露出来了更…

单片机原理及技术(五)—— 单片机与开关、键盘以及显示器件的接口设计(C51编程)

目录 一、单片机控制发光二极管显示 1.1 单片机与发光二极管的连接 1.2 拉电流和灌电流 1.3 I/O端口的编程控制 二、开关状态检测 2.1 开关控制单个LED灯亮灭 三、单片机控制LED数码管的显示 3.1 LED数码管的显示原理 3.2 LED数码管的静态显示与动态显示 3.2.1 静态显…

用不同的url头利用Python访问一个网站,把返回的东西保存为txt文件

这个需要调用requests模块&#xff08;相当于c的头文件&#xff09; import requests 还需要一个User-Agent头&#xff08;这个意思就是告诉python用的什么系统和浏览器&#xff09; Google Chrome&#xff08;Windows&#xff09;: Mozilla/5.0 (Windows NT 10.0; Win64; x64…

软件质量模型、生命周期模型、测试过程模型

目录 测试用例 定义 常见测试用例的核心8要素 软件质量模型 质量模型标准 软件开发过程模型&#xff08;软件生命周期模型&#xff09; 瀑布模型 软件测试过程模型 V模型 W模型 测试用例 定义 测试用例&#xff0c;也叫Test Case&#xff0c;为了特定的目的而设计…

【Apache Doris】数据副本问题排查指南

【Apache Doris】数据副本问题排查指南 一、问题现象二、问题定位三、问题处理 本文主要分享Doris中数据副本异常的问题现象、问题定位以及如何处理此类问题。 一、问题现象 问题日志 查询报错 Failed to initialize storage reader, tablet{tablet_id}.xxx.xxx问题说明 查…

使用Python的Turtle库绘制草莓熊

引言 Turtle库是Python标准库中一个非常有趣且实用的模块&#xff0c;它主要用于绘制图形和动画。Turtle图形学源于Logo语言&#xff0c;是一种基于命令的绘图方式。通过控制一个名为“海龟”的虚拟角色&#xff0c;在屏幕上移动和绘制&#xff0c;Turtle库可以轻松地教授基础…

IDEA工具中Java语言写小工具遇到的问题

一&#xff1a;读取excel时遇到 org/apache/poi/ss/usermodel/WorkbookProvider 解决办法&#xff1a; 在pom.xml中把poi的引文包放在最前面即可&#xff08;目前就算放在最后面也不报错了&#xff0c;不知道为啥&#xff09; 二&#xff1a;本地maven打包时&#xff0c;没有…

React基础学习-Day08

React基础学习-Day08 React生命周期&#xff08;旧&#xff09;&#xff08;新&#xff09;&#xff08;函数组件&#xff09; &#xff08;旧&#xff09; 在 React 16 版本之前&#xff0c;React 使用了一套不同的生命周期方法。这些生命周期方法在 React 16 中仍然可以使用…

【人工智能】Python实现文本转换为语音:使用gTTS库实现

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、准备工作三、使用gTTS实现文本转换为语音详细步骤 四、人工智能与TTS技术五、总结 一、引言 文本转换为语音&#xff08;Text-to-Speech&#xff0c;简称TTS&#xff09;技术是人工智能的重要组成部分&#xf…

2024年7月萤火虫航天为NASA发射8颗立方体卫星

作为美国宇航局立方体卫星发射计划的一部分&#xff0c;萤火虫航空航天公司于7月3日在该公司的阿尔法火箭上发射了八颗小型卫星。这枚名为“夏日噪音”的火箭于太平洋夏令时&#xff08;PDT&#xff09;晚上9点04分从加利福尼亚州范登堡空军基地的2号航天发射场成功升空。 立方…

SpringBoot整合SSE,实现后端主动推送DEMO

前言 说起服务端主动推送&#xff0c;大家第一个想到的一定是WEBSOCKET 。 作为软件工程师&#xff0c;不能无脑使用一种技术&#xff0c;要结合实际情况&#xff0c;择优选取。 SSE&#xff08;Server-Sent Events&#xff09;相比于WEBSOCKET 1、轻量化、兼容性 基于传统…

Mac装虚拟机占内存吗 Mac用虚拟机装Windows流畅吗

如今&#xff0c;越来越多的Mac用户选择在他们的设备上安装虚拟机来运行不同的操作系统。其中&#xff0c;最常见的是使用虚拟机在Mac上运行Windows。然而&#xff0c;许多人担心在Mac上装虚拟机会占用大量内存&#xff0c;影响电脑系统性能。此外&#xff0c;有些用户还关心在…

抖音火爆 百度地图导航高阶定制茉莉13个语音包附带安装教程,开车再也不会犯困了

慎用&#xff0c;慎用&#xff01; 1、工具下载&#xff1a; 百度导航高阶定制茉莉13个语音包https://pan.quark.cn/s/8669c1dad02a下载 | MT管理器&#xff1a;https://pan.quark.cn/s/b7b8e8f16326 2、语音包路径&#xff1a; 百度导航路径&#xff1a; /storage/emulate…

【LLM】-04-提示工程 - 文本转换

目录 1、文本翻译 1.1、翻译为德语 1.2、识别语种 1.3、多语言翻译 1.4、同时进行语气转换 1.5、通用翻译器 2、语气与写作风格调整 3、数据格式转换 4、拼写及语法纠正 5、综合样例 大语言模型具有强大的文本转换能力&#xff0c;可以实现多语言翻译、拼写纠正、语法…