数据结构——二叉树练习(深搜广搜)

数据结构——二叉树练习

  • 路径之和
  • 深度优先算法和广度优先算法
  • 二叉搜索树
  • 判断一棵二叉树是否为搜索二叉树和完全二叉树

我们今天来看二叉树的习题:

路径之和

在这里插入图片描述

https://leetcode.cn/problems/path-sum-ii/

这是一个典型的回溯,深度优先算法的题,这里我们来简单的介绍一下深度优先算法和广度优先算法:

深度优先算法和广度优先算法

深度优先搜索(Depth-First Search, DFS)和广度优先搜索(Breadth-First Search, BFS)是两种常用的图(或树)遍历算法。虽然它们都是用于探索图中所有节点的策略,但在搜索顺序和所需数据结构上有所不同。

深度优先搜索(DFS)

深度优先搜索是一种沿着图的深度方向尽可能深地搜索的算法。它会优先访问离起点最近的未访问节点的子节点,直到到达叶子节点(没有子节点的节点)或无法继续深入为止,然后回溯到上一个节点,尝试访问其未被访问的另一个子节点,重复这一过程,直到图中所有节点都被访问过。

实现方式

  • 递归实现:从某个起始节点开始,递归地访问其未访问过的子节点。
  • 栈实现:使用栈来保存待访问节点,每次从栈顶取出一个节点,访问它,并将其未访问过的子节点压入栈中。

广度优先搜索(BFS)

广度优先搜索是一种从起点开始,按层次逐层向外遍历的算法。它会先访问与起点距离最近的所有节点(即邻居节点),然后再访问这些节点的邻居节点,以此类推,直到遍历到目标节点或遍历完整个图。

实现方式

  • 队列实现:使用队列来保存待访问节点,每次从队头取出一个节点,访问它,并将其未访问过的邻居节点加入队尾。

比较

  • 搜索顺序

    • DFS:沿着一条路径深入到底,再回溯并尝试另一条路径,类似“纵深”探索。
    • BFS:从起点开始,逐层向外扩散,类似于“地毯式”搜索。
  • 所需数据结构

    • DFS:递归实现时不需要额外数据结构;栈实现时需用到栈。
    • BFS:需要使用队列。
  • 空间复杂度

    • DFS:递归实现的空间复杂度取决于递归调用的深度,最坏情况下可能达到O(n);栈实现的空间复杂度为O(n),n为图中节点数。
    • BFS:空间复杂度为O(n),需要存储所有待访问节点。
  • 适用场景

    • DFS:适用于寻找图中是否存在某条路径、求解最短路径问题(无权图)等,特别是在高度大于宽度的图中效果较好。
    • BFS:适用于求解最短路径问题(有权图需使用Dijkstra算法或A*算法等)、寻找两个节点间的最短路径、拓扑排序等问题,特别是在宽度大于高度的图中效果较好。

我们今天这道题就是一个深度优先搜索,我们拿这棵树来举例子:
在这里插入图片描述
我们用二维vector来存放满足条件的路径:
在这里插入图片描述
我们从3开始,先往左走,到9:
在这里插入图片描述
3 + 9 = 12故将3和9放入vector[0]中:
在这里插入图片描述
这个时候,往回走,回到3:
在这里插入图片描述回到3,便往右走:
在这里插入图片描述
重复上述步骤,整理思路可得代码:

class Solution {
public:
	// 定义一个成员函数 dfs,用于实现深度优先搜索,查找所有和为目标值的路径
	void dfs(TreeNode* root, vector<int>& path, vector<vector<int>>& result,
	         int targetSum)
	{
	    // 如果当前节点为空,直接返回
	    if (root == nullptr)
	    {
	        return;
	    }
	
	    // 将当前节点的值加入路径,并从目标和中减去该值
	    path.push_back(root->val);
	    targetSum -= root->val;
	
	    // 如果当前节点是叶子节点(无左右子节点),且剩余目标和为0,说明找到了一条符合条件的路径
	    if (root->left == nullptr && root->right == nullptr && targetSum == 0)
	    {
	        result.push_back(path); // 将当前路径加入结果集
	    }
	
	    // 递归遍历左子树
	    dfs(root->left, path, result, targetSum);
	
	    // 递归遍历右子树
	    dfs(root->right, path, result, targetSum);
	
	    // 回溯:从路径中移除当前节点的值,以便于后续节点的搜索
	    path.pop_back();
	}
	
	// 定义一个成员函数 pathSum,用于查找二叉树中所有和为目标值的路径
	vector<vector<int>> pathSum(TreeNode* root, int targetSum)
	{
	    // 初始化结果容器,用于存放所有和为目标值的路径
	    vector<vector<int>> result;
	
	    // 初始化当前路径向量
	    vector<int> path; // 当前路径
	
	    // 调用 dfs 函数,从根节点开始搜索
	    dfs(root, path, result, targetSum);
	
	    // 返回找到的所有和为目标值的路径
	    return result;
	}
};

二叉搜索树

二叉搜索树(Binary Search Tree, BST)是一种特殊类型的二叉树,它具有以下关键属性:

定义与性质:

有序性:对于二叉搜索树中的任意节点,其左子树中所有节点的值都严格小于该节点的值,而右子树中所有节点的值都严格大于该节点的值。这保证了树中的数据按照某种顺序排列。
递归结构:二叉搜索树的每个子节点(如果存在)本身也是一个二叉搜索树,也就是说,整个数据结构具有递归性质。

我们之前自己实现的二叉树就是二叉搜索树,如果还有小伙伴不怎么熟悉的,可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/138163494

有一个重要的性质:二叉树的中序遍历是一个递增的数列,这个用来判断搜索二叉树是一个非常关键的方法。

判断一棵二叉树是否为搜索二叉树和完全二叉树

在这里插入图片描述

https://www.nowcoder.com/practice/f31fc6d3caf24e7f8b4deb5cd9b5fa97?tpId=196&tqId=37156&ru=/exam/oj

我们可以利用二叉搜索树中序遍历的特点来判断是否为二叉搜索树,判断是否为完全二叉树,这里我们就可以借助队列,用广度优先搜索

假设我们有一棵完全二叉树:
在这里插入图片描述

如果利用队列,全部放在队列中,应该是这样的顺序:
在这里插入图片描述

如果是非完全二叉树:
在这里插入图片描述
我们发现,如果是完全二叉树,那么空节点应该全都集中在末尾,如果是非完全二叉树,中间就会出现空结点所以我们只要在遇到空结点时,检查之后是否有结点,如果没有就是完全二叉树,有的话就是非完全二叉树

// 定义一个成员函数 judgeCompelte,用于判断给定的二叉树是否为完全二叉树
bool judgeCompelte(TreeNode* root)
{
    // 初始化一个队列,用于按层遍历二叉树
    queue<TreeNode*> queue;

    // 如果根节点不为空,将其入队
    if (root)
        queue.push(root);

    // 使用队列进行层序遍历
    while (!queue.empty())
    {
        // 弹出队首节点
        TreeNode* front = queue.front();
        queue.pop();

        // 如果遇到空节点,表示已经到达当前层的最后一个有效节点,跳出循环
        if (front == nullptr)
            break;

        // 将当前节点的左右子节点(无论是否为空)依次入队,准备遍历下一层
        queue.push(front->left);
        queue.push(front->right);
    }

    // 遍历结束后,队列中剩余的节点应全为空,因为它们对应于完全二叉树中不存在的节点
    // 如果队列中还有非空节点,说明这不是完全二叉树,返回false
    while (!queue.empty())
    {
        TreeNode* front = queue.front();
        queue.pop();

        if (front)
        {
            return false;
        }
    }

    // 队列已清空,且所有弹出的节点都符合完全二叉树的条件,返回true,表示给定二叉树是完全二叉树
    return true;
}

判断是否为二叉搜索树:

// 中序遍历二叉树,并将遍历结果存储在给定的向量中
void inorder(TreeNode* root, vector<int>& vc) {
    if (root == nullptr) {
        return;
    }

    inorder(root->left, vc); // 遍历左子树
    vc.push_back(root->val); // 将当前节点的值添加到向量中
    inorder(root->right, vc); // 遍历右子树
}

// 判断给定的二叉树是否为二叉搜索树
bool isBST(TreeNode* root) {
    vector<int> vc;
    inorder(root, vc); // 对二叉树进行中序遍历

    for (int i = 0; i < vc.size() - 1; i++) {
        if (vc[i] >= vc[i + 1]) { // 如果当前元素大于或等于下一个元素,则不是二叉搜索树
            return false;
        }
    }

    return true; // 如果所有元素都小于下一个元素,则是二叉搜索树
}

那么这道题就可以迎刃而解了:

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    //判断完全是否为完全二叉树
    bool judgeCompelte(TreeNode* root)
    {
        //初始化队列
        queue<TreeNode*> queue;

        //入队
        if(root)
            queue.push(root);

    
        while(!queue.empty())
        {
            TreeNode* front = queue.front();
            queue.pop();

            if(front == nullptr)
                break;
            
            queue.push(front->left);
            queue.push(front->right);
            
        }

        while(!queue.empty())
        {
           TreeNode* front = queue.front();
           queue.pop();

            if (front)
            {
                return false;
            }
        }

        return true;
    }

    //中序遍历
    void inoder(TreeNode* root,vector<int>& vc)
    {
        if(root == nullptr)
        {
            return;
        }

        inoder(root->left,vc);
        vc.push_back(root->val);
        inoder(root->right,vc);
    }

    
    //判断
    vector<bool> judgeIt(TreeNode* root) 
    {
       vector<bool> result(2,false); 
       if(!root)
       {
            result[0] = true;
            result[1] = true;
            return result;
       }

       //判断是否为二叉搜索树
       vector<int> vc;
       inoder(root,vc);
       result[0] = true;

       for(int i = 0; i <vc.size() - 1; i++)
       {
            if(vc[i] >= vc[i+1])
            {
                result[0] = false;
                break;
            }
       }

       //判断是否为完全二叉树
      result[1] = judgeCompelte(root);

       return result; 
    }
};

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

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

相关文章

解决Win10 C盘扩展卷灰色不可用的简单方法!

当你发现电脑C盘空间不足&#xff0c;却又一段Win10 C盘扩展卷选项无法使用的状况时&#xff0c;该如何应对呢&#xff1f;本篇文章将向你介绍3种简单的方法&#xff0c;帮助你轻松解决C盘扩容的问题&#xff01; C盘扩容的重要性&#xff1f; 当前&#xff0c;大部分台式机和…

普乐蛙VR航天航空体验馆VR双人旋转座椅元宇宙VR飞船

多长假来袭&#xff01;&#xff01;想为门店寻找更多新鲜有趣的吸粉体验&#xff1f;想丰富景区体验&#xff1f;别着急&#xff0c;小编为你准备了一款爆款设备——时光穿梭机&#xff0c;720无死角旋转&#xff01;&#xff01;吸睛、刺激体验&#xff0c;将亲子、闺蜜、情侣…

【链表】Leetcode K个一组翻转链表

题目讲解 25. K 个一组翻转链表 算法讲解 虽然这道题是一道困难题&#xff0c;但是从代码层面很简单&#xff0c;只是一道简单的模拟&#xff1a;我们要先求出总共需要翻转的链表有多少组&#xff08;链表的长度 / k&#xff09;&#xff0c;接下来就是翻转k的链表最链接的问…

【论文速读】|理解基于大语言模型的模糊测试驱动程序生成

本次分享论文&#xff1a;Understanding Large Language Model Based Fuzz Driver Generation 基本信息 原文作者&#xff1a;Cen Zhang, Mingqiang Bai, Yaowen Zheng, Yeting Li, Xiaofei Xie, Yuekang Li, Wei Ma, Limin Sun, Yang Liu 作者单位&#xff1a;南洋理工大学…

Zephyr sensor子系统学习

一、背景 2023年7月份nRF Connect SDK 2.4.0最新版本&#xff0c;使用的Zephyr V3.3版本。从Zephyr 3.5版本在子系统中加入了sensing子系统。 现在最新的nRF Connect SDK 2.6.0 release支持v3.5.99-ncs1&#xff0c;已经支持sensing子系统 nRF52840现在官方支持两个传感器de…

2023最新!nginx安装配置保姆级教程

2023最新!nginx安装配置保姆级教程 这篇文章了参考了这位的教程:https://blog.csdn.net/qq_36838700/article/details/129971765 导航 文章目录 2023最新!nginx安装配置保姆级教程一、nginx下载二、编译安装nginx安装pcre安装openssl、zlib、gcc依赖安装nginx 二、拓展 一、n…

01.Scala概述及环境配置

文章目录 [toc] 1.**Scala概述**2.**Scala环境搭建**2.1下载2.2环境变量配置 1.Scala概述 特点&#xff1a; 同样运行在JVM上&#xff0c;可以与现存程序同时运行。可直接使用Java类库。同Java一样静态类型。语法和Java类似&#xff0c;比Java更加简洁&#xff08;简洁而并不…

Python-100-Days: Day01

Day01 Python简介 1.1989年Guido von Rossum在圣诞节之夜开始着手python语言编译器的编写。 2.1991年2月 Python v1 编译器诞生&#xff0c;使用C实现的&#xff0c;此时可以调用C的库函数。 3.1994年1月&#xff0c;Python v1.0 正式版发布。 4.2000年10月16日&#xff0…

2024软件测试面试题总结

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧…

农业-大量数据在数据库中做AVG如何优化

如果是直接查询呢&#xff1f; 设备每个分区3s回传一次数据 一个设备有三个分区 一分钟需要回传 3 * 20 60次 一个小时 回传 60*60 3600次 一天回传 3600 * 24 86400次 我如果想计算以天为单位的气温数据&#xff0c;需要聚合8w条数据 进行优化 一分钟60次&#xff0c…

To String的几个作用

To String的几个作用 一、Object类中toString的作用 1、在主方法中我们可以直接用toString输出对象其中的内容 2、我们需要直接输出对象中所属内容时&#xff0c;直接使用toString方法输出语句&#xff0c;输出内容不友好&#xff0c;不便于阅读 子类&#xff1a; public c…

【快速上手ESP32(基于ESP-IDFVSCode)】11-MQTT

MQTT MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;是一种基于发布/订阅模式的轻量级通讯协议&#xff0c;构建于TCP/IP协议之上。它最初由IBM在1999年发布&#xff0c;主要用于在硬件性能受限和网络状况不佳的情况下&…

如何使用 Fly.io 和 Tigris 部署 Next.js 应用

在本教程中&#xff0c;您将学习到应用部署平台 Fly.io 和全球分布式的 S3 兼容对象存储服务 Tigris。 这两个平台密切相关&#xff0c;使它们成为您项目的绝佳选择。您可以从 Fly.io 获得应用部署体验&#xff0c;并从 Tigris 获得对象存储功能。 应用部署相当简单易懂&…

短视频素材去哪里找,而且不带水印的那种?

为了确保视频创作者能够接触到全球范围内的优质资源&#xff0c;下面列出的视频素材网站各具特色&#xff0c;提供从标准视频到高动态范围&#xff08;HDR&#xff09;的素材&#xff0c;满足你在不同项目中的需求。 1. 蛙学府 (中国) 提供专业级的视频素材&#xff0c;特别适…

【C++】STL-vector的使用

目录 1、什么是vector&#xff1f; 2、vector的使用 2.1 vector的定义 ​编辑 2.2 遍历修改数据 2.3 迭代器 2.4 vector空间增长问题 2.5 vector的增删查改 3、迭代器失效 3.1 会引起其底层空间改变的操作&#xff0c;都有可能是迭代器失效 3.2 指定位置元素的删除操…

【触摸案例-多点触摸的案例 Objective-C语言】

一、我们来做这个多点触摸的案例 1.首先呢,按着这个option键啊,可以模拟多点触摸, 然后呢,再去怎么着去画圈儿, 它这个里边就会产生一个imageView,跟着你去变,会有这么一个效果, 那么,首先啊,我们新建一个项目, Name:03-多点触摸的案例 1)首先,我们把控制器的v…

dwc3控制器是怎么处理otg

概念 在OTG中&#xff0c;初始主机设备称为A设备&#xff0c;外设称为B设备。可用电缆的连接方式来决定初始角色。两用设备使用新型Mini-AB插座&#xff0c;从而使Mini-A插头、Mini-B插头和Mini-AB插座增添了第5个引脚&#xff08;ID&#xff09;&#xff0c;以用于识别不同的…

网御星云防火墙策略配置

网御星云防火墙配置 1. 初始设定2. 网络配置3. 安全规则和策略4. 监控和维护零基础入门学习路线视频配套资料&国内外网安书籍、文档网络安全面试题 1. 初始设定 接入网络&#xff1a; 在开始配置之前&#xff0c;确保你的网御星云防火墙正确连接到网络。这通常涉及将WAN接…

基于Python实现的推箱子小游戏

Python贪吃蛇小游戏实现: 推箱子曾经在我们的童年给我们带来了很多乐趣。推箱子这款游戏现在基本上没人玩了&#xff0c;甚至在新一代人的印象中都已毫无记忆了。。。但是&#xff0c;这款游戏可以在一定程度上锻炼自己的编程能力。 运行效果如图所示&#xff1a; 游戏关卡有点…

Ubuntu系统强制用户设置复杂密码

1、安装cracklib模块 安装PAM的cracklib模块&#xff0c;cracklib能提供额外的密码检查能力 sudo apt-get install libpam-cracklib2、可用vim打开配置文件&#xff08;或其它方式&#xff09; sudo vim /etc/pam.d/common-password3、设置密码复杂度 在# here are the per…