深入了解二叉搜索树:原理、操作与应用

news2024/11/28 1:35:42

文章目录

  • 二叉搜索树
    • 二叉搜索树的操作
    • 1.查找操作
    • 2.插入操作
    • 3.查找最大值或者最小值
    • 4.删除操作
    • 5.前序中序后序遍历
  • 总结

在这里插入图片描述

二叉搜索树

在这里插入图片描述

形如上图的二叉树就是二叉搜索树,接下来我们来具体阐述一下什么是二叉搜索树。

二叉搜索树的概念:满足左子树的值小于根节点,右子树的值大于根节点的值,这样的树就是二叉搜索树

二叉搜索树的性质:
1.二叉搜索树的中序遍历呈现单调递增的性质。
2.二叉搜索树的每个节点的值都具有唯一性。

二叉搜索树的操作

对于普通的二叉树来说,增删查改没有意义,但是对于二叉搜索树来说增删查改便有了意义,接下来,我们来研究二叉搜索树的增删查改等等一系列操作。
首先我们先定义一个二叉搜索树,二叉搜索树的定义和二叉树的定义相同:

class TreeNode
{
public:
private:
	int _val;
	TreeNode* _left;
	TreeNode* _right;
};
class BST
{
public:
private:
	TreeNode* _root;
};

上面就是二叉搜索树的定义

接下来我们来写一下二叉搜索树的接口,,我们先将其列在BST

class BST
{
public:
	//初始化
	BST();
	//查找
	bool Search(int val);
	bool SearchNode(TreeNode* Node, int val);
	//插入
	void Insert(int val);
	TreeNode* InsertNode(TreeNode* Node, int val);
	//删除
	void Delete(int val);
	TreeNode* AssistDelete(TreeNode* Node, int val);
	TreeNode* FindPrev(TreeNode* root, TreeNode* Node);
	//查找最大值或者最小值
	int GetMin();
	TreeNode* AssistGetMin(TreeNode*Node);
	int GetMax();
	TreeNode* AssistGetMax(TreeNode* Node);
	//后序遍历
	void PostOrder();
	void AssistPostOrder(TreeNode* Node);
	//中序遍历
	void InOrder();
	void AssistInOrder(TreeNode* Node);
	//前序遍历
	void PrevOrder();
	void AssistPrevOrder(TreeNode* Node);
private:
	TreeNode* _root;
};

接下我们一个一个来探讨

1.查找操作

//查找
bool Search(int val);
bool SearchNode(TreeNode* Node, int val);

找到了返回true,没找到返回false
对于普通的二叉树来说我们需要遍历整个树对其进行查找,而且可能二叉树中还有重复值的节点,但是对于二叉搜索树就没有这种麻烦,当我们要搜索一个数时,只需要将这个数和根节点的值进行比较,如果比根节点的数大就递归到右边,如果比根节点的数小就递归左边,不需要整个树都递归。

我们来看看具体代码:

bool BST::Search(int val)
{
	return SearchNode(_root, val);
}
//辅助函数
bool BST::SearchNode(TreeNode* Node, int val)
{
	//找到了nullptr就说明没找到,直接返回false
	if (Node == nullptr)
	{
		return false;
	}
	//判断val的位置,对左子树或者右子树进行递归
	if (Node->_val == val)
	{
		return true;
	}
	else if (val < Node->_val)
	{
		return SearchNode(Node->_left, val);
	}
	else
	{
		return SearchNode(Node->_right, val);
	}
}

2.插入操作

对于普通二叉树来说,插入操作没有意义,因为每一个地方都可以插入,并没有实际意义,但是对于二叉搜索树来说就有意义了,对于二叉搜索树来说,插入操作具有唯一性,可以维护二叉搜索树的排序的性质。

//插入
void Insert(int val);
TreeNode* InsertNode(TreeNode* Node, int val);

查到插入位置然后返回,InsertNode是一个辅助函数。
具体代码:

void BST::Insert(int val)
{
	_root = InsertNode(_root, val);
}
TreeNode* BST::InsertNode(TreeNode* Node, int val)
{
	//当Node==nullptr的时候说明找到了插入的位置
	if (Node == nullptr)
	{
		创造一个新的节点,用val进行初始化
		return new TreeNode(val);//创建一个节点
	}
	//判断递归的范围
	if (Node->_val < val)
	{
		Node->_right = InsertNode(Node->_right, val);
	}
	else if (Node->_val > val)
	{
		Node->_left = InsertNode(Node->_left, val);
	}
	//最后返回Node
	return Node;
}

3.查找最大值或者最小值

//查找最大值或者最小值
int GetMin();
TreeNode* AssistGetMin(TreeNode*Node);
int GetMax();
TreeNode* AssistGetMax(TreeNode* Node);

由于二叉搜索树的特殊性质,左子树的值一定比右子树小,说明最大值一定在右子树的最右边的一个节点上,而最小值一定在左子树的最左边的一个节点上。

我们来看看代码:

//查找最小值
int BST::GetMin()
{
	//根节点为空的时候,说明没有,直接返回INT_MAX
	if (_root == nullptr)
	{
		return INT_MAX;
	}
	//找到最小值的节点
	TreeNode* min = AssistGetMin(_root);
	//返回最小值
	return min->_val;
}
TreeNode* BST::AssistGetMin(TreeNode* Node)
{
	//直接递归左子树,当左子树指向的左边是空的时候直接返回当前节点
	if (Node->_left == nullptr)
	{
		return Node;
	}
	//递归左子树
	return AssistGetMin(Node->_left);
}
//查找最大值
int BST::GetMax()
{
	//同上
	if (_root == nullptr)
	{
		return INT_MAX;
	}
	//找到最大值对应的节点
	TreeNode* max = AssistGetMax(_root);
	//返回最大值
	return max->_val;
}
TreeNode* BST::AssistGetMax(TreeNode* Node)
{
	//判断边界条件
	if (Node->_right == nullptr)
	{
		return Node;
	}
	//递归右子树
	return AssistGetMax(Node->_right);
}

4.删除操作

//删除
void Delete(int val);
TreeNode* AssistDelete(TreeNode* Node, int val);
TreeNode* FindPrev(TreeNode* root, TreeNode* Node);

对于删除操作存在三种情况:
1. 删除的当前节点的左节点和右节点都是nullpt
2. 删除的当前节点的的左节点或者右节点当中存在一个节点,有一个节点是nullpt
3. 删除的当前节点的左节点和右节点都不为nullptr

对于删除操作我们还需要一个函数就是能找到前一个节点的函数,当我们删除了一个节点之后,我们需要找到前一个节点将它与后一个节点连接起来,还需要一个函数就是我们刚刚写的找最大值的函数或者找最小值的函数,这里我们就用找最小值的函数,对于删除的当前节点的左节点和右节点都不为空的时候,我们需要有一个节点来重新构造一下这个二叉搜索树,这里有个技巧,就是我们需要的节点就是当前节点的左子树的最大值的节点或者是右子树的最小值的节点充当本节点。

代码展示:

void BST::Delete(int val)
{
	_root = AssistDelete(_root, val);
}
//找到前一个节点
TreeNode* BST::FindPrev(TreeNode* root, TreeNode* Node)
{
	if (root->_left == Node || root->_right == Node)
	{
		return root;
	}
	if (root->_val < Node->_val)
	{
		FindPrev(root->_right, Node);
	}
	if (root->_val > Node->_val)
	{
		FindPrev(root->_left, Node);
	}
}
//删除操作
TreeNode* BST::AssistDelete(TreeNode* node, int val)
{
	//当node==nullptr说明没有满足条件的删除节点,直接返回nullpr
	if (node == nullptr)
	{
		return node;
	}
	// 找到要删除的节点
	if (val < node->_val)
	{
		node->_left = AssistDelete(node->_left, val);
	}
	else if (val > node->_val)
	{
		node->_right = AssistDelete(node->_right, val);
	}
	//找到了之后进入else进行删除操作
	else
	{
		// 要删除的节点有一个或没有孩子
		if (node->_left == nullptr)
		{
			TreeNode* temp = node->_right;
			delete node;
			return temp;
		}
		else if (node->_right == nullptr)
		{
			TreeNode* temp = node->_left;
			delete node;
			return temp;
		}

		// 要删除的节点有两个孩子
		// 找到要删除节点的后继节点(右子树中的最小节点)
		TreeNode* temp = AssistGetMin(node->_right);
		// 将后继节点的值复制到要删除的节点中
		node->_val = temp->_val;
		// 递归删除后继节点
		node->_right = AssistDelete(node->_right, temp->_val);
	}
	//返回
	return node;
}

5.前序中序后序遍历

	//后序遍历
	void PostOrder();
	void AssistPostOrder(TreeNode* Node);
	//中序遍历
	void InOrder();
	void AssistInOrder(TreeNode* Node);
	//前序遍历
	void PrevOrder();
	void AssistPrevOrder(TreeNode* Node);

和普通二叉树相同

void BST::PostOrder()
{
	AssistPostOrder(_root);
}
void BST::AssistPostOrder(TreeNode* Node)
{
	if (Node == nullptr)
	{
		return;
	}
	AssistPostOrder(Node->_left);
	AssistPostOrder(Node->_right);
	cout << Node->_val << ' ';
}
void BST::InOrder()
{
	AssistInOrder(_root);
}
void BST::AssistInOrder(TreeNode* Node)
{
	if (Node == nullptr)
	{
		return;
	}
	AssistInOrder(Node->_left);
	cout << Node->_val << ' ';
	AssistInOrder(Node->_right);
}
void BST::PrevOrder()
{
	AssistPrevOrder(_root);
}
void BST::AssistPrevOrder(TreeNode* Node)
{
	if (Node == nullptr)
	{
		return;
	}
	cout << Node->_val << ' ';
	AssistPrevOrder(Node->_left);
	AssistPrevOrder(Node->_right);
}

总结

总的来说,二叉搜索树(BST)作为一种重要的数据结构,在计算机科学领域发挥着重要作用。通过其排序性质和高效的搜索、插入和删除操作,二叉搜索树成为了解决各种问题的有力工具。

在本博客中,我们深入探讨了二叉搜索树的概念、性质和操作。我们了解到,二叉搜索树具有自平衡的能力,能够在平均情况下保持较低的时间复杂度。同时,我们也注意到了在极端情况下,二叉搜索树可能会退化为链表,导致操作的时间复杂度上升。因此,在实际应用中,需要考虑树的平衡性,以保证其性能。

通过本博客,希望读者能够深入理解二叉搜索树的工作原理,并且能够运用这一数据结构解决实际问题。同时,也希望读者能够进一步探索二叉搜索树的相关内容,如平衡二叉搜索树(如AVL树和红黑树)以及其他高级数据结构,从而拓展自己的知识领域。

最后,二叉搜索树是计算机科学中的基础之一,深入了解它将有助于我们更好地理解和应用数据结构与算法,提高编程能力,并解决更复杂的计算问题。

在这里插入图片描述

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

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

相关文章

NVIDIA 配置 Jetson 扩展针座

系列文章目录 前言 每个 Jetson 开发套件包括多个扩展接头和连接器&#xff08;统称 "接头"&#xff09;&#xff1a; 40 针扩展接头&#xff1a; 可让您将 Jetson 开发套件连接到现成的 Raspberry Pi HAT&#xff08;顶部附加硬件&#xff09;&#xff0c;如 Seee…

智慧公厕:打造智能、安全、舒适的公共厕所新时代

随着智慧城市建设的不断推进&#xff0c;公共设施的智能化也已成为一种必然趋势。在这一背景下&#xff0c;智慧公厕作为城市管理的一个重要方面&#xff0c;正逐渐走进人们的视野。通过对所在辖区内所有公共厕所的全域感知、全网协同、全业务融合以及全场景智慧的赋能&#xf…

保姆级Lora炼丹教程,让你实现真人模特定制

最近发现很多朋友学会了Stable Diffusion后&#xff0c;都是停留在“玩”的层面。但我觉得让大家“用”起来&#xff0c;才是关键 于是我思考了很久&#xff0c;找出了SD在“应用”层面&#xff0c;最重要的两个功能&#xff1a;Lora和ControlNet Lora负责把自己生活中有关联的…

一篇教你学会HTML:常用标签 | 表格 | 表单 | 特殊符号转义

标题标签 <h1></h1>....<h6></h6> <h1>一级标题</h1><h2>二级标题</h2><h3>三级标题</h3>我们可以添加 align属性 来改变标签的位置 (左对齐&#xff0c;居中&#xff0c;右对齐)&#xff0c;还可以设置颜色等。 …

InfiniGate自研网关实现四

13.服务发现组件搭建和注册网关连接 以封装 api-gateway-core 为目的&#xff0c;搭建 SpringBoot Starter 组件&#xff0c;用于服务注册发现的相关内容处理。 这里最大的目的在于搭建起用于封装网关算力服务的 api-gateway-core 系统&#xff0c;提供网关服务注册发现能力。…

什么是包装ERP软件

在当今的商业环境中&#xff0c;ERP软件已经成为了企业管理的关键工具。然而&#xff0c;许多企业主可能还不完全明白什么是ERP软件&#xff0c;特别是包装ERP软件。 首先&#xff0c;我们需要了解ERP软件的基本概念。它是一种集成的软件应用程序&#xff0c;旨在帮助企业管理…

HTML+VUE3组合式+ELEMENT的容器模板示例(含侧栏导航,表格,...)

一个简单的在html中使用Vue3及Element-plus vue-icons的整合示例&#xff1a; 一、示例截图 二、文件代码 直接复制到html文件在浏览器打开即可预览 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title&g…

智慧仓储可视化大屏,以最直观的形式展示海量数据。

智慧仓储可视化大屏是一种通过数据可视化技术&#xff0c;将仓储管理系统中的海量数据以图表、地图、仪表盘等形式直观展示在大屏上的解决方案。它可以帮助仓储管理人员更清晰地了解仓库的运营情况&#xff0c;从而做出更明智的决策。 智慧仓储可视化大屏通常包括以下功能和特点…

React 第二十六章 Hook useCallback

useCallback 是 React 提供的一个 Hook 函数&#xff0c;用于优化性能。它的作用是返回一个记忆化的函数&#xff0c;当依赖发生变化时&#xff0c;才会重新创建并返回新的函数。 在 React 中&#xff0c;当一个组件重新渲染时&#xff0c;所有的函数都会被重新创建。这可能会…

如何通过汽车制造供应商协同平台,提高供应链的效率与稳定性?

汽车制造供应商协同是指在汽车制造过程中&#xff0c;整车制造商与其零部件供应商之间建立的一种紧密合作的关系。这种协同关系旨在优化整个供应链的效率&#xff0c;降低成本&#xff0c;提高产品质量&#xff0c;加快创新速度&#xff0c;并最终提升整个汽车产业的竞争力。以…

vue2基础语法01——基础语法使用了解

vue2基础语法01——基础语法使用了解 1. vue模板语法1.1 插值语法1.2 指令语法1.3 简单测试完整代码 2. vue中各选项使用&#xff08;简单说几个&#xff09;2.1 el选项2.2 data选项2.2.1 简述2.2.2 data选项的两种类型2.2.3 注意&#xff08;限制&#xff09;2.2.4 更多了解参…

JAVA快速工具代码集

一、前言 在开发过程中&#xff0c;特别是维护老系统&#xff0c;有时候想使用的工具类却使用不了。又要重新造轮子。所以准备点工具类代码是必须的&#xff0c;无奈之举。 二、JSON数据转换 String content cdfQhOrderResModel.getContent(); List<CdfQH…

Python 数据库操作- sqlite3 模块

Python sqlite3 模块 1. 安装 SQLite3 可使用 sqlite3 模块与 Python 进行集成。sqlite3 模块是由 Gerhard Haring 编写的。它提供了一个与 PEP 249 描述的 DB-API 2.0 规范兼容的 SQL 接口。用户不需要单独安装该模块&#xff0c;因为 Python 2.5.x 以上版本默认自带了该模块…

在uniapp里面使用 mp-html 并且开启 latex 功能

在uniapp里面使用 mp-html 并且开启 latex 功能 默认情况下 mp-html 是不会开启 latex 功能的, 如果需要开启 latex 功能是需要到代码操作拉取代码自行打包的。 这里说一下 mp-html 里面的 latex 功能是由 https://github.com/rojer95/katex-mini 提供的技术实现&#xff0c;…

【Spark】Spark编程体验,RDD转换算子、执行算子操作(六)

Spark编程体验 项目依赖管理 <dependencies><dependency><groupId>org.scala-lang</groupId><artifactId>scala-library</artifactId><version>2.12.10</version></dependency><dependency><groupId>org.ap…

通过 Java 操作 redis -- zset 有序集合基本命令

目录 使用命令 zadd&#xff0c;zrange 使用命令 zcard 使用命令 zrem 使用命令 zscore 使用命令 zrank 关于 redis zset 有序集合类型的相关命令推荐看Redis - Zset 有序集合 要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务器&#xff0c;推荐看通过 Jav…

武汉凯迪正大—超声波探伤仪的主要功能

武汉凯迪正大超声波探伤仪的主要功能 高精度定量、定位&#xff0c;满足了较近和较远距离探伤的要求&#xff1b; 近场盲区小&#xff0c;满足了小管径、薄壁管探伤的要求&#xff1b; 自动校准&#xff1a;一键式自动校准&#xff0c;操作非常便捷&#xff0c;自动测试探头的…

基于springboot实现贸易行业crm系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现贸易行业crm系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于springboot的贸易行业crm系统的开发全过程。通过分析基于springboot的贸易行业crm系统管理的不足&#xff0c;创建…

element ui的无法关掉的提示弹框

使用element的$alert组件的属性把X去掉和确定按钮和取消按钮去掉&#xff1b; import { MessageBox } from element-ui; MessageBox.alert(AI功能已到期或暂未开启, 友情提示, {showClose: false,showCancelButton: false,showConfirmButton: false }); 如果在router的路由守…

华为ensp中BFD和OSPF联动(原理及配置命令)

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年5月6日20点26分 BFD通常指的是双向转发检测。BFD是一个旨在快速检测通信链路故障的网络协议&#xff0c;提供了低开销、短延迟的链路故障检测机制。它主要用于监测两个…