数据结构:二叉树OJ题篇 手把手带你入门数据结构~

news2024/9/28 21:39:41

文章目录

  • 前言
  • 一、单值二叉树
  • 二、检查两颗树是否相同
  • 三、对称二叉树
  • 四、另一颗树的子树
  • 五、二叉树的前序遍历
  • 六、二叉树的后序遍历
  • 七、二叉树中序遍历
  • 八、二叉树的构建及遍历
  • 九、二叉树选择题
    • 1.二叉树性质
    • 2. 二叉树选择题
      • 1. 某⼆叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该⼆叉树中的叶⼦结点数为?
      • 2. 在具有 2n 个结点的完全⼆叉树中,叶⼦结点个数为?
      • 3. ⼀棵完全⼆叉树的结点数位为531个,那么这棵树的⾼度为?
      • 4. 一个具有 767 个结点的完全⼆叉树,其叶⼦结点个数为?
      • 5. 某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为?
      • 6. ⼆叉树的先序遍历和中序遍历如下:
      • 7. 设⼀棵⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为?
      • 8. 某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的序列为?
  • 总结


前言

在这里插入图片描述

经历了对于二叉树的学习,相信大家对于二叉树一定有了深入的了解,接下来和J桑一起来刷起题来吧~


一、单值二叉树

单值二叉树
在这里插入图片描述

在这里插入图片描述

bool isUnivalTree(struct TreeNode* root) {

    if(root == NULL)
    {
        return true;
    }
    if(root->left && root->val != root->left->val)
    {
        return false;
    }
    if(root->right && root->val != root->right->val)
    {
        return false;
    }
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

二、检查两颗树是否相同

检查两颗树是否相同
在这里插入图片描述
在这里插入图片描述

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    if(p == NULL && q == NULL)
    {
        return true;
    }
    if(p == NULL || q == NULL)
    {
        return false;
    }
    
    if(p->val != q->val)
    {
        return false;
    }

    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);

}

三、对称二叉树

对称二叉树
在这里插入图片描述
各位有没有发现对称的树,和上一道题相等的树很像呢?
没错,只是p树在遍历的时候先遍历左孩子,再遍历右孩子。
而q树,先遍历右孩子,在遍历左孩子。

在这里插入图片描述

typedef struct TreeNode TreeNode;

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    if(p == NULL && q == NULL)
    {
        return true;
    }
    if(p == NULL || q == NULL)
    {
        return false;
    }
    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left, q->right) && isSameTree(p->right, q->left);

}

bool isSymmetric(struct TreeNode* root) 
{
    if(root == NULL) 
    {
        return true; // 空树是对称的
    }
    return   isSameTree(root->left, root->right);
}

四、另一颗树的子树

另一颗树的子树
在这里插入图片描述

另一个树是否是这棵树的子树呢?
要解决这个问题,我们还需要用到两个树是否相同。

在这里插入图片描述

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    if(p == NULL && q == NULL)
    {
        return true;
    }
    if(p == NULL || q == NULL)
    {
        return false;
    }
    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) 
{
    if(root == NULL)
    {
        return false;
    }
    
    if(isSameTree(root, subRoot))
    {
        return true;
    }

    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); 
}

五、二叉树的前序遍历

二叉树的前序遍历
在这里插入图片描述
在这里插入图片描述

并且它的输出是一个数组
在这里插入图片描述
它的返回值是int* 类型
在这里插入图片描述

为了返回这个数组,我们需要先获取树中结点个数。

前面我们实现过返回结点个数~

可以这样想, 一个结点的个数等于其左右子树结点个数之和加上它本身。
在这里插入图片描述
只要分别找到每一个结点左子树和右子树结点之和,就是我们的答案。
将大事化小,当root为NULL的时候结束,不正是递归的思想吗?

// ⼆叉树结点个数
// 一个结点的个数等于其左右子树结点个数之和加上它本身
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

第二步: 动态的给数组申请内存

int* returnArr = (int* )malloc(sizeof(int) * (*returnSize));

第三步: 前序遍历树

前面也讲过~
对于前序遍历来说,就是按照 根----左----右的顺序进行遍历。
如下图所示:
在这里插入图片描述

对于每个根节点来说,它的遍历方法都是 根----左----右,我们有时候可能认为遍历到一个结点的左孩子或者右孩子就要回去,其实是不对的。因为它的孩子的遍历方式也是 根----左----右

typedef struct TreeNode TreeNode;

int BinaryTreeSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}


void PreOrder(TreeNode* root, int* arr, int* pi)
{
	if (root == NULL)
	{
		return;
	}
	
	arr[(*pi)++] = root->val;
	PreOrder(root->left, arr, pi);
	PreOrder(root->right, arr, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) 
{
    //第一步求出树中结点个数
    *returnSize = BinaryTreeSize(root);

    //第二步动态的给数组申请内存
    int* returnArr = (int* )malloc(sizeof(int) * (*returnSize));

    //第三步前序遍历树
    int i = 0;
    PreOrder(root, returnArr, &i);

    return returnArr;
}

六、二叉树的后序遍历

二叉树的后序遍历

在这里插入图片描述
后序遍历与前序遍历思路一样。
唯一不同的就是遍历顺序变为左----右----根
在这里插入图片描述

typedef struct TreeNode TreeNode;

int BinaryTreeSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}


void PostOrder(TreeNode* root, int* arr, int* pi)
{
	if (root == NULL)
	{
		return;
	}
	
	
	PostOrder(root->left, arr, pi);
	PostOrder(root->right, arr, pi);
    arr[(*pi)++] = root->val;
}


int* postorderTraversal(struct TreeNode* root, int* returnSize) 
{
     //第一步求出树中结点个数
    *returnSize = BinaryTreeSize(root);

    //第二步动态的给数组申请内存
    int* returnArr = (int* )malloc(sizeof(int) * (*returnSize));

    //第三步前序遍历树
    int i = 0;
    PostOrder(root, returnArr, &i);

    return returnArr;
}

七、二叉树中序遍历

二叉树中序遍历
在这里插入图片描述
中序遍历与前序遍历思路一样。
唯一不同的就是遍历顺序变为左----根----右
在这里插入图片描述

typedef struct TreeNode TreeNode;

int BinaryTreeSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}


void InOrder(TreeNode* root, int* arr, int* pi)
{
	if (root == NULL)
	{
		return;
	}
	
	
	InOrder(root->left, arr, pi);
    arr[(*pi)++] = root->val;
	InOrder(root->right, arr, pi);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) 
{
    //第一步求出树中结点个数
    *returnSize = BinaryTreeSize(root);

    //第二步动态的给数组申请内存
    int* returnArr = (int* )malloc(sizeof(int) * (*returnSize));

    //第三步前序遍历树
    int i = 0;
    InOrder(root, returnArr, &i);

    return returnArr;   
}

八、二叉树的构建及遍历

二叉树的构建及遍历
在这里插入图片描述
我们先来进行思考,既然你要遍历字符串,那我们就要先获取字符串。

#include <stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

int main() 
{
    // 1. 读取字符串
    char arr[100];
    scanf("%s",arr);

    
    return 0;
}

获取了字符串后,我们要将每一个字符放入二叉树中,那么我们就要多次创立结点

BTNode* buyNode(char x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->_data = x;
	newnode->_left = newnode->_right = NULL;
	return newnode;
}

拿到了结点之后我们要将结点放入二叉树中,这里用的是前序遍历的方法

在这里插入图片描述

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
    if(a[(*pi)] == '#')
    {
        (*pi)++;
        return NULL;
    }

    BTNode* root = buyNode(a[(*pi)++]);
    root->_left = BinaryTreeCreate(a, pi);
    root->_right = BinaryTreeCreate(a, pi);

    return root;
}

在这里插入图片描述
最后我们中序遍历就可以了~

总结如下:

#include <stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>


typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

BTNode* buyNode(char x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->_data = x;
	newnode->_left = newnode->_right = NULL;
	return newnode;
}

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
    if(a[(*pi)] == '#')
    {
        (*pi)++;
        return NULL;
    }

    BTNode* root = buyNode(a[(*pi)++]);
    root->_left = BinaryTreeCreate(a, pi);
    root->_right = BinaryTreeCreate(a, pi);

    return root;
}

void InOrder(BTNode* root)
{
    if(root == NULL)
    {
        return;
    }

    InOrder(root->_left);
    printf("%c ",root->_data);
    InOrder(root->_right);
}

int main() 
{
    // 1. 读取字符串
    char arr[100];
    scanf("%s",arr);
    // 2. 根据字符串创立二叉树
    //这里我们用前序遍历的方法创建
    int i = 0;
    BTNode* root = BinaryTreeCreate(arr,&i);

    // 3. 最后我们中序输出
    InOrder(root);
    
    return 0;
}

九、二叉树选择题

1.二叉树性质

⼆叉树性质:

对任何⼀棵⼆叉树, 如果度为 0 其叶结点个数为 n0 , 度为 2 的分⽀结点个数为 n2 ,则有:
n0 = n2 + 1

在这里插入图片描述

证明上述性质: 假设⼀个⼆叉树有 a 个度为2的节点, b 个度为1的节点, c 个叶节点,则这个⼆叉树的边数是 2a+b。
另⼀⽅⾯,由于共有 a+b+c 个节点,所以边数等于 a+b+c-1 结合上⾯两个公式: 2a+b = a+b+c-1 ,
即: a = c-1


2. 二叉树选择题

1. 某⼆叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该⼆叉树中的叶⼦结点数为?

根据二叉树的性质,叶子结点数 = 度为2的结点数 + 1。

  • 给定度为2的结点数为199,那么叶子结点数 = 199 + 1 = 200。
    答案:B

2. 在具有 2n 个结点的完全⼆叉树中,叶⼦结点个数为?

完全二叉树有以下性质:

  • 叶子结点数 = ⌈n/2⌉
  • 题中总结点数为 2n,则叶子结点数 = n。
    答案:A

3. ⼀棵完全⼆叉树的结点数位为531个,那么这棵树的⾼度为?

完全二叉树的高度公式为:高度 = ⌊log2(N)⌋,其中N是结点数。

  • 计算 log2(531) ≈ 9.05,因此高度为 10。
    答案:B

4. 一个具有 767 个结点的完全⼆叉树,其叶⼦结点个数为?

完全二叉树的性质:当有 N 个结点时,叶子结点数大约为 ⌊(N + 1) / 2⌋。

  • 对于 767 个结点,叶子结点数为 ⌊(767 + 1) / 2⌋ = 384。
    答案:B

5. 某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为?

  • 按前序遍历顺序,先访问根结点,再访问左子树,最后访问右子树。
  • 根据完全二叉树的结构,前序序列应为 ABDHECFG。
    答案:A

6. ⼆叉树的先序遍历和中序遍历如下:

先序遍历:EFHIGJK;
中序遍历:HFIEJKG。
从先序遍历中可以看出,E 是根结点。
答案:A

7. 设⼀棵⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为?

  • 根据后序遍历可知,a 是根结点。
  • 从中序遍历可以将其分为两部分:b 是左子树,dce 是右子树。
  • 对右子树dce的后序遍历是dec,因此d为右子树的根结点。
    最终前序遍历序列为 adbce。
    答案:A

8. 某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的序列为?

  • 如果后序遍历和中序遍历相同,这说明二叉树可能是一个退化的二叉树(链状结构),其层次遍历应与它们相同。
    答案:A

总结

到这里,我们二叉树的知识就讲啦!
J桑还是有点手忙脚乱的,各位观众老爷感觉怎么样呢?

谢谢大家!

在这里插入图片描述

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

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

相关文章

vLLM (6) - Scheduler BlockSpaceManager

系列文章目录 vLLM (1) - Qwen2推理&部署 vLLM (2) - 架构总览 vLLM (3) - Sequence & SequenceGroup vLLM (4) - LLMEngine上篇 vLLM (5) - LLMEngine下篇 vLLM (6) - Scheduler & BlockSpaceManager 文章目录 系列文章目录前言一、Scheduler1.概述2.Scheduler._…

Cannot solve model: no CPLEX runtime found.【macOS系统下问题解决】

最近在研究电能优化的策略时&#xff0c;运行别人代码出现了 Cannot solve model: no CPLEX runtime found. 1. 下载cplex # !pip install cplex12.8 #指定版本 !pip install cplex #下载最新的版本2. 下载docplex !pip install docplex3. 重启Jupyter或者你的项目…

C++之STL—常用排序算法

sort (iterator beg, iterator end, _Pred) // 按值查找元素&#xff0c;找到返回指定位置迭代器&#xff0c;找不到返回结束迭代器位置 // beg 开始迭代器 // end 结束迭代器 // _Pred 谓词 random_shuffle(iterator beg, iterator end); // 指定范围内的元素随机调…

Qt(9.28)

widget.cpp #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {QPushButton *btn1 new QPushButton("登录",this);this->setFixedSize(640,480);btn1->resize(80,40);btn1->move(200,300);btn1->setIcon(QIcon("C:…

Secret Configmap

应用启动过程中可能需要一些敏感信息&#xff0c;比如访问数据库的用户名&#xff0c;密码或者秘钥&#xff0c;讲这些信息直接保存在容器镜像中显然不合适&#xff0c;kubernetes提供的解决方案就是Secret Secret会以密文的方式存储数据&#xff0c;避免了直接在配置文件中保…

基于php的医院信息管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

NLP:BERT的介绍

1. BERT 1.1 Transformer Transformer架构是一种基于自注意力机制(self-attention)的神经网络架构&#xff0c;它代替了以前流行的循环神经网络和长短期记忆网络&#xff0c;已经应用到多个自然语言处理方向。   Transformer架构由两个主要部分组成&#xff1a;编码器(Encod…

《向量数据库指南》——Zilliz Cloud Serverless版震撼发布:弹性伸缩,成本直降50倍

在数据驱动的时代背景下,向量数据库作为处理复杂非结构化数据(如图像、视频、音频及文本等)的关键技术,正逐步成为推动人工智能、机器学习以及大数据分析等领域发展的核心力量。随着数据量的爆炸性增长和查询需求的多样化,如何高效地管理并利用这些数据成为了企业和开发者…

如何回答:count(*) 和 count(1)的区别

感谢Java面试教程的Java多线程文章&#xff0c;点击查看>原文 在SQL查询中&#xff0c;count(*) 和 count(1) 都是用于统计表中行数的聚合函数&#xff0c;它们的主要区别在于语法和执行效率上。 语法上的区别&#xff1a; count(*)&#xff1a;直接统计表中的所有行数&…

RabbitMQ的各类工作模式介绍

简单模式 P: ⽣产者, 也就是要发送消息的程序 C: 消费者,消息的接收者 Queue: 消息队列, 图中⻩⾊背景部分. 类似⼀个邮箱, 可以缓存消息; ⽣产者向其中投递消息, 消费者从其中取出消息.特点: ⼀个⽣产者P&#xff0c;⼀个消费者C, 消息只能被消费⼀次. 也称为点对点(Point-to-…

[CKA]CKA预约和考试

CKA预约和考试 一、预约 1、登录Linux Foundation https://trainingportal.linuxfoundation.org/learn/dashboard 2、首页点 "Resume"进行预约 3、进入考试准备界面后&#xff0c;按要求分别验证 Agree to Global Candidate Agreement&#xff08;同意全球候选人协…

nodejs逐字读取文件示例

像chatpGPT显示文字一样.主要是服务器流式返回数据.前端用for await读取response.body <button id"fetchjson" onclick"FetchJSON()">fetch json看console与network</button> <button id"fetchstream" onclick"FetchStrea…

基于php的民宿预订管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

[SAP ABAP] SELECT-OPTIONS

基本语法 SELECT-OPTIONS <sel> FOR <f>. 示例1 输出结果&#xff1a; 点击右边的 按钮&#xff0c;将弹出多项数值输入界面&#xff0c;如下图所示 示例2 数据准备 学生表(ZDBT_STU_437) 学生表(ZDBT_STU_437)数据明细 输出结果&#xff1a; OBLIGATORY参数用于…

RTA-OS Port Guide学习(三)-基于S32K324 OS

文章目录 前言HardwareSupported DevicesRegister UsageInitializationModificationRequired OS resourcesInterruptsInterrupt Priority LevelsAllocation of ISRs to Interrupt VectorsVector TableWriting Category 1 Interrupt HandlersWriting Category 2 Interrupt Handl…

ECCV`24 | 高保真目标修复新SOTA!复旦智象开源CAT-Diffusion,语义视觉双一致

文章链接&#xff1a;https://arxiv.org/pdf/2409.08260 Github链接&#xff1a;https://github.com/Nnn-s/CATdiffusion 总结速览 解决的问题: 单一U-Net在所有去噪步骤中对齐文本提示和视觉对象不足以生成期望的对象。 扩散模型的复杂采样空间中无法保证对对象生成的可控性…

基于php的助农生鲜销售系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Elasticsearch7.7设置账号密码时的逻辑矛盾问题和文章相关评论

一、Elasticsearch7.7设置账号密码时的逻辑矛盾问题 publish:June 19, 2020 -Friday 2019年1月30日&#xff0c;外媒又报道了一起Elasticsearch数据泄露事件&#xff01;2019年1月份的至少有6起Elasticsearch数据泄露事件了。原因何在&#xff0c;很简单&#xff0c;开发者在服…

数据的表示和存储 第3讲 C语言中的整数

深耕AI ​互联网行业 算法研发工程师 概括 本讲主要介绍了C语言中的整数表示。 无符号整数能够表示的最大值比带符号整数要大。带符号整数使用补码来表示&#xff0c;补码的运算系统是一种模运算系统&#xff0c;能够实现加减运算的统一。在C语言中&#xff0c;如果一个表达式…

7.MySQL内置函数

目录 日期函数时间函数字符串函数数学函数其他函数 日期函数 函数名称描述current_date()当前日期current_time()当前时间current_timesamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(date, interval d_value_tyep)在date中添加日期函数或时间。interval后…