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

难度参考

        难度:中等

        分类:二叉树

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

题目

        给定二叉搜索树(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.mfbz.cn/a/380001.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CUDA简介

CPUGPU异构计算 GPU计算并不是指单独的GPU计算&#xff0c;而是指CPUGPU的异构计算。一块单独的GPU是无法独立的完成所有计算任务的&#xff0c;它必须在CPU的调度下才能完成特定的任务。CPU更适合进行逻辑复杂低并行的程序&#xff0c;GPU更适合逻辑简单高并行的任务。这主要…

问题:必须坚持以中国式现代化推进中华民族伟大复兴,既不走封闭僵化的老路,也不走 #媒体#知识分享

问题&#xff1a;必须坚持以中国式现代化推进中华民族伟大复兴&#xff0c;既不走封闭僵化的老路&#xff0c;也不走 A、中国特色社会主义道路 B、改革开放之路 C、改旗易帜的邪路 D、中国式现代化之路 参考答案如图所示

HarmonyOS 鸿蒙 ArkTS 双色旋转动画效果

下载地址&#xff1a; https://download.csdn.net/download/weixin_54226053/88818859 也可以点击顶部的资源下载

【Git】Windows下通过Docker安装GitLab

私有仓库 前言基本思路拉取镜像创建挂载目录创建容器容器启动成功登录仓库设置中文更改密码人员审核配置邮箱 前言 由于某云存在人数限制&#xff0c;这个其实很好理解&#xff0c;毕竟使用的是云服务器&#xff0c;人家也是要交钱的。把代码完全放在别人的服务器上面&#xf…

Qt网络编程-ZMQ的使用

不同主机或者相同主机中不同进程之间可以借助网络通信相互进行数据交互&#xff0c;网络通信实现了进程之间的通信。比如两个进程之间需要借助UDP进行单播通信&#xff0c;则双方需要知道对方的IP和端口&#xff0c;假设两者不在同一主机中&#xff0c;如下示意图&#xff1a; …

C#,十进制展开数(Decimal Expansion Number)的算法与源代码

1 十进制展开数 十进制展开数&#xff08;Decimal Expansion Number&#xff09;的计算公式&#xff1a; DEN n^3 - n - 1 The decimal expansion of a number is its representation in base -10 (i.e., in the decimal system). In this system, each "decimal place…

戴上HUAWEI WATCH GT 4,解锁龙年新玩法

春节将至&#xff0c;华为WATCH GT 4作为一款颜值和实力并存的手表&#xff0c;能为节日增添了不少趣味和便利。无论你是钟情于龙年表盘或定制属于自己的表盘&#xff0c;还是过年用来抢红包或远程操控手机拍全家福等等&#xff0c;它都能成为你的“玩伴”。接下来&#xff0c;…

C++后端开发之Sylar学习三:VSCode连接Ubuntu配置Gitee

C后端开发之Sylar学习三&#xff1a;VSCode连接Ubuntu配置Gitee 为了记录学习的过程&#xff0c;学习Sylar时写的代码统一提交到Gitee仓库中。 Ubuntu配置Gitee 安装git sudo apt-get install -y git配置用户名和邮箱 git config --global user.name 用户名 …

产品效果图为何要用渲染100农场?渲染100邀请码1a12

产品效果图很重要&#xff0c;它能帮助设计人员和消费者理解产品特点&#xff0c;是不可或缺的一步。产品效果图渲染耗时耗力&#xff0c;不仅慢而且容易出错&#xff0c;在这种情况下&#xff0c;使用渲染农场就成了必备选择&#xff0c;以目前国内最好的渲染农场渲染100为例&…

【芯片设计- RTL 数字逻辑设计入门 番外篇 9 -- SOC 中PL端与PS端详细介绍】

文章目录 Programmable Logic and Processing SystemPL&#xff08;Programmable Logic&#xff09;特点PS和PL之间的协同设计和开发工具 Programmable Logic and Processing System 在系统级芯片&#xff08;SoC&#xff09;的上下文中&#xff0c;“PL” 通常指的是可编程逻…

JavaScript基础第六天

JavaScript 基础第六天 今天我们学习数组的遍历&#xff0c;以及数组的其他用法。 1. 数组遍历 1.1. 古老方法 可以使用 for 循环进行遍历。 let arr ["a", "b", "d", "g"]; for (let i 0; i < arr.length; i) {console.log…

HiveSQL——用户中两人一定认识的组合数

注&#xff1a;参考文章&#xff1a; SQL之用户中两人一定认识的组合数--HQL面试题36【快手数仓面试题】_sql面试题-快手-CSDN博客文章浏览阅读1.2k次&#xff0c;点赞3次&#xff0c;收藏12次。目录0 需求分析1 数据准备2 数据分析3 小结0 需求分析设表名&#xff1a;table0现…

Jupyter Notebook如何在E盘打开

Jupyter Notebook如何在E盘打开 方法1&#xff1a;方法2&#xff1a; 首先打开Anaconda Powershell Prompt, 可以看到默认是C盘。 可以对应着自己的界面输入&#xff1a; 方法1&#xff1a; (base) PS C:\Users\bella> E: (base) PS E:\> jupyter notebook方法2&#x…

分析 丨ToF传感器的XR应用和主要厂商

苹果MR头显Vision Pro被业界关注&#xff0c;另有消息称华为在2024年规划2款产品&#xff0c;一个是与Vision Pro、Quest和PICO方案类似的MR头显&#xff0c;预计2024年Q3或者Q4发布&#xff1b;另一个是与魅族MYVU衍射光波导AR眼镜类似的产品&#xff0c;发布时间晚于MR头显。…

数码管扫描显示-单片机通用模板

数码管扫描显示-单片机通用模板 一、数码管扫描的原理二、display.c的实现1、void Display(void) 各模式界面定义数据2、void BackupRamToDisRam(void)从缓存区刷新显示映射Ram3、void FreshDisplay(void) 映射显示Ram到主控的IO口4、void LcdDisplay_8bit(void) 映射显示Ram到…

[leetcode] 32. 最长有效括号

文章目录 题目描述解题方法方法一&#xff1a;栈java代码复杂度分析 方法二&#xff1a;贪心java代码复杂度分析 相似题目 题目描述 给你一个只包含 ( 和 ) 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 示例 1&#xff1a; 输…

[Java][算法 哈希]Day 01---LeetCode 热题 100---01~03

LeetCode 热题 100---01~03 ------->哈希 第一题 两数之和 思路 最直接的理解就是 找出两个数的和等于目标数 这两个数可以相同 但是不能是同一个数字&#xff08;从数组上理解就是内存上不是同一位置&#xff09; 解法一&#xff1a;暴力法 暴力解万物 按照需求 …

spring-security authentication persistence

翻译版本【spring-security 6.2.1】persistence Persisting Authentication 用户第一次请求受保护的资源时&#xff0c;系统会提示他们输入凭据。提示输入凭据的最常见方法之一是将用户重定向到登录页面。未经身份验证的用户请求受保护的资源的HTTP交换可能如下所示: 例1。未…

前端实现支付跳转以及回跳

// 支付地址 const baseURL http://pcapi-xiaotuxian-front-devtest.itheima.net/ const backURL http://127.0.0.1:5173/paycallback const redirectUrl encodeURIComponent(backURL) const payUrl ${baseURL}pay/aliPay?orderId${route.query.id}&redirect${redirec…

PyTorch 2.2 中文官方教程(一)

PyTorch 秘籍 PyTorch 秘籍 原文&#xff1a;pytorch.org/tutorials/recipes/recipes_index.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 秘籍是关于如何使用特定 PyTorch 功能的简短、可操作的示例&#xff0c;与我们的全长教程不同。 PyTorch 原型示例 原文…