算法练习-二叉搜索树中的搜索(思路+流程图+代码)

news2025/1/16 16:03:14

难度参考

        难度:中等

        分类:二叉树

        难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。且所在课程未提供测试平台,故实现代码主要为自行测试的那种,以下内容均为个人笔记,旨在督促自己认真学习。

题目

        给定二叉搜索树(BST)的根节点和一个值。你需要在BST中找到节点值等于给定值的节点。返回以该节点为根的子树。如果节点不存在,则返回NULL.
        示例1:
        输入:root=[4,2,7,1,3],val=2
        输出:[2,1,3]

        示例2:
        输入:root=[4,2,7,1,3],val=5
        输出:[]
        提示:
        树中节点数在[1,5000]范围内
        1<=Node.Va1<=10(7)
        root是二叉搜索树
        1<=val<=10(7)
        额外:
        希望你可以尝试使用迭代法,尤其要考虑二叉搜索树的特性,来优化迭代。

思路

        这个问题要求在一个二叉搜索树中查找一个特定值的节点,并且返回以这个节点为根的子树。如果找不到这个值,则返回NULL。由于这是一个二叉搜索树,我们可以利用其特性来指导搜索过程,使之比一般的二叉树更高效。在二叉搜索树中,对于任何节点,其左子树中的所有节点都小于这个节点,而右子树中的所有节点都大于这个节点。

        基于这个性质,我们可以使用如下思路来进行查找:

  1. 从树的根节点开始搜索。
  2. 比较当前节点的值与目标值:
    • 如果当前节点的值等于目标值,那么我们找到了目标节点,返回这个节点即可。
    • 如果目标值小于当前节点的值,那么我们应该在左子树中继续搜索。
    • 如果目标值大于当前节点的值,那么我们应该在右子树中继续搜索。
  3. 如果当前节点是NULL,表示我们已经到达了叶子节点但未找到目标值,此时应该返回NULL。
  4. 重复以上步骤直到找到目标值或遍历到了叶子节点。

示例

        假设我们有如下的二叉搜索树结构:

        4
       / \
      2   7
     / \
    1   3

        现在让我们分两个示例来查找值为2的节点。

        示例一:查找值为2的节点

  1. 我们从根节点开始,也就是值为4的节点。
  2. 因为2小于4,我们向左子树移动。
  3. 现在我们在值为2的节点。我们比较当前节点的值(2)与目标值(2),发现它们相等。
  4. 我们找到了目标节点,并返回这个节点。

        函数返回包含值为2的子树的根,也就是:

    2
   / \
  1   3

        示例二:查找值为5的节点

  1. 我们从根节点开始,也就是值为4的节点。
  2. 因为5大于4,我们向右子树移动。
  3. 现在我们在值为7的节点。因为5小于7,我们向左子树移动。
  4. 在值为7的节点处,并没有左子节点,所以我们到达了NULL。
  5. 我们没有找到目标节点,返回NULL。

梳理

        这样的实现能够工作,因为它依赖于二叉搜索树(Binary Search Tree, BST)的基本性质。在二叉搜索树中,每个节点都满足以下条件:

  1. 节点的左子树中的每个节点的值都小于当前节点的值。
  2. 节点的右子树中的每个节点的值都大于当前节点的值。
  3. 左子树和右子树也分别是二叉搜索树。

        这个性质允许我们使用二分查找的方法快速地在树中定位一个值是否存在。具体到 searchBST 函数中的实现:

  • 开始查找:我们从根节点开始查找。
  • 比较值:我们将目标值与当前节点的值进行比较。
    • 如果目标值与当前节点的值相等,我们就找到了需要的节点,返回它;
    • 如果目标值小于当前节点的值,根据二叉搜索树的性质,我们知道目标值(如果存在于树中)必定在当前节点的左子树中。因此,我们更新当前节点为其左子节点,继续查找;
    • 如果目标值大于当前节点的值,那么目标值(同样如果存在)一定在当前节点的右子树中。因此,我们更新当前节点为其右子节点,继续查找。
  • 终止条件:这个过程会一直进行,直到当前节点为空(这意味着目标值不存在于树中,返回 nullptr)或者找到了一个节点的值等于目标值(返回该节点)。

代码

#include <iostream> // 包含标准输入输出流的库

using namespace std; // 使用命名空间std,省去std::前缀

struct TreeNode { // 定义二叉树节点结构
    int val; // 节点存储的值
    TreeNode *left; // 指向左子树的指针
    TreeNode *right; // 指向右子树的指针
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} // 初始化构造函数,nullptr表示空指针
};

TreeNode* searchBST(TreeNode* root, int val) { // 定义搜索二叉搜索树的函数
    while (root != nullptr && root->val != val) { // 当树不为空且当前节点值不等于目标值时
        root = val < root->val ? root->left : root->right; // 判断目标值是在左子树还是右子树
    }
    return root; // 返回找到的节点指针,如果没找到则是nullptr
}

int main() { // 主函数
    TreeNode* root = new TreeNode(4); // 创建根节点,赋值为4
    root->left = new TreeNode(2); // 创建根的左子节点,赋值为2
    root->right = new TreeNode(7); // 创建根的右子节点,赋值为7
    root->left->left = new TreeNode(1); // 创建左子节点的左子节点,赋值为1
    root->left->right = new TreeNode(3); // 创建左子节点的右子节点,赋值为3

    int search_val = 2; // 设置要查找的值为2
    TreeNode* result = searchBST(root, search_val); // 调用搜索函数
    if (result != nullptr) { // 如果搜索结果不为空
        cout << "搜索到节点值为 " << search_val << " 的节点是:" << result->val << endl;
        if (result->left != nullptr) // 如果搜索到的节点的左子树不为空
            cout << "左子节点:" << result->left->val << endl; // 打印左子节点的值
        if (result->right != nullptr) // 如果搜索到的节点的右子树不为空
            cout << "右子节点:" << result->right->val << endl; // 打印右子节点的值
    } else { // 如果搜索结果为空
        cout << "未找到节点值为 " << search_val << " 的节点" << endl; // 表明没找到节点
    }

    search_val = 5; // 设置要查找的值为5
    result = searchBST(root, search_val); // 再次调用搜索函数
    if (result != nullptr) { // 如果搜索结果不为空
        cout << "搜索到节点值为 " << search_val << " 的节点是:" << result->val << endl;
        if (result->left != nullptr) // 如果搜索到的节点的左子树不为空
            cout << "左子节点:" << result->left->val << endl;
        if (result->right != nullptr) // 如果搜索到的节点的右子树不为空
            cout << "右子节点:" << result->right->val << endl;
    } else { // 如果搜索结果为空
        cout << "未找到节点值为 " << search_val << " 的节点" << endl; // 表明没找到节点
    }
    // 释放动态分配的内存(没写,懒)
    return 0; // 主函数结束,返回0
}  

        时间复杂度:O(n)

        空间复杂度:O(n)

打卡

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

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

相关文章

二、OpenAI开发者快速入门

启动并运行OpenAI API OpenAI API 为开发者提供一个简单的接口&#xff0c;使其能够在他们的应用中创建一个智能层&#xff0c;由OpenAI最先进的模型提供支持。聊天补全端点为ChatGPT提示支持&#xff0c;一种简单的方法是&#xff1a;输入文本&#xff0c;使用GPT-4模型输出。…

在JSP中实现JAVABEAN

在JSP中实现JAVABEAN 问题陈述 创建Web应用程序以连接数据库并检索作者名、地址、城市、州及邮政编码等与作者的详细信息。JavaBean组件应接受作者ID、驱动程序名及URL作为参数。信息要从authors表中检索。 解决方案 要解决上述问题,需要执行以下任务: 创建Web应用程序。创…

macbookair怎么清理内存 ?如何利用 CleanMyMac X 进行系统清理

macbookair怎么清理内存 清理MacBook Air的内存可以通过以下几种方法&#xff1a; 优化储存空间。在MacBook Air上&#xff0c;可以通过“优化储存空间”来释放空间。这包括将文件储存在iCloud中&#xff0c;如桌面、文稿和iCloud信息&#xff0c;以及自动移除在iCloud中观看…

Lombok 高级说明

优质博文&#xff1a;IT-BLOG-CN 一、痛点 【1】代码臃肿&#xff1a;POJO中的getter/setter/equals/hashcode/toString等&#xff1b; 【2】样板式代码&#xff1a;I/O流的关闭操作等&#xff1b; Lombok是一个可以通过注解简化Java代码开发的工具&#xff0c;能够在我们编…

2.8日学习打卡----初学RabbitMQ(三)

2.8日学习打卡 一.springboot整合RabbitMQ 之前我们使用原生JAVA操作RabbitMQ较为繁琐&#xff0c;接下来我们使用 SpringBoot整合RabbitMQ&#xff0c;简化代码编写 创建SpringBoot项目&#xff0c;引入RabbitMQ起步依赖 <!-- RabbitMQ起步依赖 --> <dependency&g…

关节点检测

https://www.bilibili.com/video/BV19g4y1777q/?p2&spm_id_frompageDriver 关节点检测全流程 YOLO:单阶段&#xff0c;快&#xff1b; MMPose&#xff1a;双阶段&#xff0c;准&#xff1b; 标注工具Labelme 用Labelme标注样本数据集

利用Pybind11封装Python版的WiringPi!

原版的WiringPi是一个用于树莓派的GPIO库&#xff0c;用C语言开发&#xff0c;仓库地址&#xff1a;https://github.com/WiringPi/WiringPi。该库允许用户以编程方式访问和控制树莓派的GPIO引脚。而随着Python在嵌入式设备上的快速发展&#xff0c;其对底层引脚的操作也变得越来…

OpenAI给DALL-E 3来了个新动作,加入了全新水印技术

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

老胡的周刊(第128期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 coze-discord-proxy[2] 代理 Discord-Bot 对…

018 Linux

文章目录 操作系统定义分类Linux系统构成 Linux文件系统Linux常用命令基础操作命令文件操作压缩解压权限管理显示展示命令其他命令 vi编译器操作使用 添加用户基本概念用户管理命令 ubuntu软件安装ssh服务终端启动Python服务 操作系统 定义 操作系统是管理计算机硬件与软件资…

【超高效!保护隐私的新方法】针对图像到图像(l2l)生成模型遗忘学习:超高效且不需要重新训练就能从生成模型中移除特定数据

针对图像到图像生成模型遗忘学习&#xff1a;超高效且不需要重新训练就能从生成模型中移除特定数据 提出背景如何在不重训练模型的情况下从I2I生成模型中移除特定数据&#xff1f; 超高效的机器遗忘方法子问题1: 如何在图像到图像&#xff08;I2I&#xff09;生成模型中进行高效…

archlinux 使用 electron-ssr 代理 socks5

提前下载好 pacman 包 https://github.com/shadowsocksrr/electron-ssr/releases/download/v0.2.7/electron-ssr-0.2.7.pacman 首先要有 yay 和 aur 源&#xff0c;这个可以参考我之前的博客 虚拟机内使用 archinstall 安装 arch linux 2024.01.01 安装依赖 yay 安装的&#…

堆排序----C语言数据结构

目录 引言 堆排序的实现**堆的向下调整算法** 对排序的时间复杂度建堆的时间复杂度&#xff1a;排序过程的时间复杂度&#xff1a;总体时间复杂度&#xff1a; 引言 堆排序&#xff08;Heap Sort&#xff09;是一种基于比较的排序算法&#xff0c;利用堆的数据结构来实现。它的…

数据湖的整体思路

湖本质上是一个集中化&#xff0c;中心化的&#xff0c;一体化的存储技术&#xff0c;并且在其之上追求技术架构的统一化&#xff0c;如流批一体&#xff0c;服务分析一体化。 当数据湖成为中心&#xff0c;那么就可以围湖而建“数据服务环”&#xff0c;环上的服务包括了数仓、…

基于tomcat运行jenkins常见的报错处理

目录 1.jenkins.util.SystemProperties$Listener错误 升级jdk11可能遇到的坑 2.java.lang.RuntimeException: Fontconfig head is null, check your fonts or fonts configuration 3.There were errors checking the update sites: UnknownHostException:updates.jenkins.i…

JAVA Web 学习(五)Nginx、RPC、JWT

十二、反向代理服务器——Nginx 支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量&#xff0c;其占用内存少、并发能力强、能支持…

初识Solidworks:我的第一份作业的感想

从来没用CAD软件画过机械设计图。但我脑子里有一种概念&#xff0c;无非就是把尺规作图软件化&#xff0c;更方便画图、更方便修改、更方便打印一些。但第一份 Solidworks 作业就颠覆了我的认知&#xff0c;考虑到这个软件的上市时间&#xff0c;让我意识到自己对 CAD 软件的认…

【大厂AI课学习笔记】【1.5 AI技术领域】(8)文本分类

8,9,10&#xff0c;将分别讨论自然语言处理领域的3个重要场景。 自然语言处理&#xff0c;Natual Language Processing&#xff0c;NLP&#xff0c;包括自然语言识别和自然语言生成。 用途是从非结构化的文本数据中&#xff0c;发掘洞见&#xff0c;并访问这些信息&#xff0…

C++——二叉树

引入 map和set特性需要先铺垫二叉搜索树&#xff0c;而二叉搜索树也是一种树形结构 二叉搜索树的特性了解&#xff0c;有助于更好的理解map和set的特性 1.二叉搜索树的概念及优缺点 1.1二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或…

CSP-202109-1-数组推导

CSP-202109-1-数组推导 解题思路 如果 currentValue 与 previousValue 相同&#xff0c;说明这个值不是一个独特的新值&#xff0c;因此只将它加到 sumTotal 上。如果 currentValue 与 previousValue 不相同&#xff0c;说明这是一个新的独特值&#xff0c;因此既将它加到 su…