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

文章目录

  • 二叉搜索树
    • 二叉搜索树的操作
    • 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就说明没找到,直接返回falseif (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);}//最后返回Nodereturn Node;
}

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

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

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

我们来看看代码:

//查找最小值
int BST::GetMin()
{//根节点为空的时候,说明没有,直接返回INT_MAXif (_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说明没有满足条件的删除节点,直接返回nullprif (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.mzph.cn/web/9540.shtml

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

相关文章

经济学SSCI期刊,中科院3区,IF=2+,难度不大,收稿范围广泛!

一、期刊名称 Information Economics and Policy 二、期刊简介概况 期刊类型&#xff1a;SSCI 学科领域&#xff1a;经济学 影响因子&#xff1a;2.8 中科院分区&#xff1a;3区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$3190 三、…

C++ | Leetcode C++题解之第78题子集

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> t;vector<vector<int>> ans;void dfs(int cur, vector<int>& nums) {if (cur nums.size()) {ans.push_back(t);return;}t.push_back(nums[cur]);dfs(cur 1, nums);t.po…

yum仓库和NFS网络共享服务

一、yum 1.1yum的定义 yum是一个基于RPM包&#xff0c;构建的软件更新机制&#xff0c;能够自动解决软件包之间的依赖关系。解决了日常工作中的大量查找安装依赖包的时间 为什么会有依赖关系的发生 因为linux本身就是以系统简洁为自身优势&#xff0c;所以在安装操作系统的时…

Docker与Harbor:构建企业级私有Docker镜像仓库

目录 引言 一、本地私有仓库 &#xff08;一&#xff09;基本概述 &#xff08;二&#xff09;搭建本地私有仓库 1.下载registry镜像 2.启动容器 3.上传本地镜像 4.客户端下载镜像 二、Harbor简介 &#xff08;一&#xff09;什么是 Harbor &#xff08;二&#xff…

苹果15能用哪些充电宝?充电宝什么牌子好?好用充电宝排名

随着移动设备的普及和功能的不断强大&#xff0c;我们对于充电宝的需求也越来越高。尤其是对于苹果15用户来说&#xff0c;选择一款兼容性好、性能稳定的充电宝显得尤为重要。在市面上众多充电宝品牌中&#xff0c;如何选择适合苹果15的充电宝&#xff1f;究竟哪个牌子的充电宝…

在线扭蛋机小程序:商家稳占市场的新突破口

近几年&#xff0c;扭蛋机进入了爆发期&#xff0c;动漫、游戏的发展更是推动了市场的发展&#xff0c;我国扭蛋机正在蓬勃发展中。 不过&#xff0c;在市场规模扩大下&#xff0c;扭蛋机行业的竞争力也在同时加大&#xff0c;企业商家需要在市场竞争中寻求发展新思路&#xf…

C#进阶-OleDb操作Excel和数据库

在C#编程中&#xff0c;使用OleDb可以方便地实现对Excel文件和数据库的操作。本文探讨了在C#中使用OleDb技术操作Excel和数据库的策略。文章详述了OleDb的定义、配置环境的步骤&#xff0c;并通过实际代码示例演示了如何高效读写Excel文件和交互数据库。文中还评估了OleDb技术的…

KaiwuDB 参编的《分析型数据库技术要求》标准正式发布

近期&#xff0c;中国电子工业标准化技术协会正式发布团体标准《分析型数据库技术要求》&#xff08;项目号&#xff1a;T-CESA 2023-006&#xff09;。该标准由中国电子技术标准化研究院、KaiwuDB&#xff08;上海沄熹科技有限公司&#xff09; 等国内 16 家企业联合起草&…

AI图书推荐:给自媒体创作者的ChatGPT使用指南

你是否厌倦了花费数小时盯着空白屏幕&#xff0c;努力为你的内容想出新鲜点子&#xff1f;想要将你的写作提升到下一个水平&#xff1f;有了ChatGPT&#xff0c;你可以告别写作障碍、无休止的修订和浪费的时间。 在这本全面的指南中&#xff0c;你将学到关于ChatGPT你需要知道…

Hive两代命令行客户端(Hive、Beeline)

Hive命令行客户端 Hive有两个主要的客户端工具&#xff0c;分别是旧版的Hive CLI&#xff08;Command Line Interface&#xff09;和新版的Beeline。 1. Hive CLI&#xff1a; Hive CLI 是 Hive 最早期的命令行客户端工具&#xff0c;它使用 JDBC 连接到 Hive 服务器&#xff…

轻松管理文件夹批量重命名:学会用关键词批量替换文件夹名称技巧

随着计算机中存储的文件和文件夹数量不断增加&#xff0c;如何有效地管理和组织它们变得尤为重要。批量重命名文件夹是提升文件管理效率的关键步骤之一。而利用云炫文件管理器中关键词批量替换文件夹名称的技巧&#xff0c;则可以帮助我们更快速地完成这一任务。 关键词批量替…

国内首发 | CSA大中华区启动《AI安全产业图谱(2024)》调研

在人工智能&#xff08;AI&#xff09;技术的快速发展浪潮中&#xff0c;AI安全已成为全球关注的焦点。为应对AI安全带来的挑战&#xff0c;确保AI技术的健康发展&#xff0c;全球范围内的研究机构、企业和技术社区都在积极探索解决方案。 在这一背景下&#xff0c;CSA大中华区…

什么是短信群发上行和下行

短信群发是一种广泛应用于商业和个人通信的技术&#xff0c;通过一次多条的方式&#xff0c;可以快速高效地传递信息。在实际的群发过程中&#xff0c;会涉及到上行和下行的概念。本文将详细介绍什么是短信群发上行和下行&#xff0c;并解释它们的应用。 什么是短信群发上行 群…

面试中算法(使用栈实现队列)

使用栈来模拟一个队列&#xff0c;要求实现队列的两个基本操作:入队、出队。 栈的特点&#xff1a;先入后出&#xff0c;出入元素都是在同一端&#xff08;栈顶&#xff09;。 队列的特点&#xff1a;先入先出&#xff0c;出入元素是在两端&#xff08;队头和队尾)。 分析&…

OKHTTP 3.12.0 以后版本 headers 中不可携带中文

今天遇到的报错&#xff1a; java.lang.llegalArgumentException: Unexpected char 0x957f at 0 in x-brand value: 电视堆栈 okhttp3.Headers.checkValue(Headers.java:272) okhttp3.Headers$Builder.add(Headers.java:312) okhttp3.Request$Builder.addHeader(Request.iava:…

MySQL数据库——基础事务操作-BEGIN-COMMIT-ROLLBACK

DDL CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT COMMENT 学号,createDate datetime DEFAULT NULL,userName varchar(20) DEFAULT NULL,pwd varchar(36) DEFAULT NULL,phone varchar(11) DEFAULT NULL,age tinyint(3) unsigned DEFAULT NULL,sex char(2) DEFAU…

内存卡不小心格式化了怎么办?3个方法解决数据丢失问题!

“很奇怪&#xff0c;我的内存卡不小心中病毒了&#xff0c;刚刚在清理病毒时不小心把内存卡格式化了。我保存了很多重要的数据在里面&#xff0c;还有方法可以恢复这些数据吗&#xff1f;” 在数字设备日益普及的今天&#xff0c;内存卡已成为我们存储和传输数据的重要工具。但…

笨方法自学python(五)

字符串和文本 在这章习题中我们将使用复杂的字符串来建立一系列的变量&#xff0c;从中你将学到它们的用途。首先我们解释一下字符串是什么 东西。 字符串通常是指你想要展示给别人的、或者是你想要从程序里“导出”的一小段字符。Python 可以通过文本里的双引号 " 或者单…

成为一名算法工程师需要掌握哪些技术栈

成为算法工程师需要学习的编程技能主要包括以下几个方面&#xff1a; Python&#xff1a;Python是算法工程师最常使用的编程语言之一。它拥有简洁易读的语法和丰富的库&#xff0c;如NumPy、Pandas、SciPy、Matplotlib等&#xff0c;这些库为数据处理、科学计算和可视化提供了…

C#开发的网络速度计 - 开源研究系列文章 - 个人小作品

上次发布了一个获取网络速度的例子( https://www.cnblogs.com/lzhdim/p/18167854 )&#xff0c;就是为了这次这个例子。用于在托盘里显示网络速度的图标&#xff0c;并且能够显示网络速度。下面就介绍一下这个小应用的源码。 1、 项目目录&#xff1b; 2、 源码介绍&#xff1b…