数据结构第十讲:二叉树OJ题

news2025/4/5 5:31:26

数据结构第十讲:二叉树OJ题

  • 1.单值二叉树
  • 2.相同的树
  • 3.对称二叉树
  • 4. 另一棵树的子树
  • 5.二叉树的前序遍历
  • 6.二叉树的中序遍历
  • 7.二叉树的后序遍历
  • 8.二叉树的构建及其遍历
  • 9.二叉树选择题
    • 9.1二叉树性质1
    • 9.2二叉树性质2
    • 9.3二叉树性质三
    • 9.4选择题

1.单值二叉树

链接: OJ题链接
在这里插入图片描述

typedef struct TreeNode TreeNode;

bool isUnivalTree(struct TreeNode* root) {
    //这一题要对二叉树结点进行逐一遍历,这里要用到递归
    //递归结束条件:
    if(root == NULL)
    {
        return true;
    }
    if(root->left && root->left->val != root->val)
    {
        return false;
    }
    if(root->right && root->right->val != root->val)
    {
        return false;
    }

    //我们想要的是每个结点都具有相同的值,所以就需要左树和右树上结点的数据都相同
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

2.相同的树

链接: OJ题链接
在这里插入图片描述

typedef struct TreeNode TreeNode;

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //要检查两棵树是否相同,就要同时遍历两棵树的结点,还是要用到递归
    //递归结束条件
    //当两个结点全为空时,返回true
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //当两个结点不全为空
    //当两个结点中有一个为空时,说明两棵树不同
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //当两棵树的结点值不同时,返回false
    if(p->val != q->val)
    {
        return false;
    }

    //最后要得到的是两棵树是否相同,就要看两棵树的左节点树和右节点树是否相同
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

3.对称二叉树

链接: OJ题链接
在这里插入图片描述

这一题和上一题差不多,属于上一题的拓展,需要注意的是,这一题要求的是是否对称,而上一题要求的是是否相同,对称要求一棵树的左结点和另一棵树的右节点相同,就这一点与上一题不同

typedef struct TreeNode TreeNode;

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //要检查两棵树是否对称,就要同时遍历两棵树的结点,还是要用到递归
    //递归结束条件
    //当两个结点全为空时,返回true
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //当两个结点不全为空
    //当两个结点中有一个为空时,说明两棵树不同
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //当两棵树的结点值不同时,返回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);
}

4. 另一棵树的子树

链接: OJ题链接
在这里插入图片描述

这一题仍然需要利用相同的树那一题的方法,不同的是,对于这一题的返回值,return的应该是左树中存在目标子树右树中存在目标子树,只要一颗树中存在目标子树,就返回true

typedef struct TreeNode TreeNode;

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //要检查两棵树是否相同,就要同时遍历两棵树的结点,还是要用到递归
    //递归结束条件
    //当两个结点全为空时,返回true
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //当两个结点不全为空
    //当两个结点中有一个为空时,说明两棵树不同
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //当两棵树的结点值不同时,返回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;
    }

    //对于返回值,只要左右树中有一棵树中存在目标子树,就需要返回true
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

5.二叉树的前序遍历

链接: OJ题链接
在这里插入图片描述

这一题与之前所写的前序遍历不同,之前所写的前序遍历都是将数直接打印出来,而这里的前序遍历要求将遍历的数依次存储在数组中,而且,题目还有一个提示:在这里插入图片描述
也就是说,函数返回的是一个数组,数组是由动态内存开辟的空间

typedef struct TreeNode TreeNode;

int TreeSize(TreeNode* root)
{
    //递归结束条件
    if(root == NULL)
    {
        return 0;
    }
    //需要返回的是根节点的数目+左节点树的结点树+右结点树的结点数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

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

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //1.首先,我们要确定需要开辟空间的大小,然后开辟空间
    //注意,这里要用*returnSize表示结点个数,从函数声明中可以分析得出
    *returnSize = TreeSize(root);
    int* arr = (int*)malloc((*returnSize)*sizeof(int));
    //2.其次就是递归遍历二叉树的结点,然后将结点的值存储在数组中
    int i = 0;
    TreePreOrder(root, arr, &i);
    return arr;
}

后续还要实现二叉树的中序遍历和二叉树的后续遍历,思路和这一个是一样的,自行实现即可

6.二叉树的中序遍历

链接: OJ题链接

typedef struct TreeNode TreeNode;

int TreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

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

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    //1.先求出需要开辟空间的大小
    *returnSize = TreeSize(root);
    //2.开辟空间
    int* arr = (int*)malloc((*returnSize) * sizeof(int));
    //3.将数据通过中序遍历进行存储
    int i = 0;
    TreeInOrder(root, arr, &i);
    return arr;
}

7.二叉树的后序遍历

链接: OJ题链接

typedef struct TreeNode TreeNode;

int TreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

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

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    //1.先求出需要开辟空间的大小
    *returnSize = TreeSize(root);
    //2.开辟空间
    int* arr = (int*)malloc((*returnSize) * sizeof(int));
    //3.将数据通过后序遍历进行存储
    int i = 0;
    TreeInOrder(root, arr, &i);
    return arr;
}

8.二叉树的构建及其遍历

链接: OJ题链接

与力扣的题目不同,这道题出自于牛客网,所给出的不仅仅是一个片段,是一段程序的接口,而是自己手动实现全部的代码:在这里插入图片描述
在这里插入图片描述
这道题中,数组插入二叉树的结构应该为:
在这里插入图片描述
下面的CreatTree方法应该好好记着

//二叉树结点结构体
typedef struct TreeNode
{
    char val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode;

TreeNode* CreatTreeNode(char x)
{
    TreeNode* newnode = (TreeNode*)malloc(sizeof(TreeNode));
    newnode->val = x;
    newnode->left = newnode->right = NULL;
    return newnode;
}
//--------------------------------------------------------------------------------
TreeNode* CreatTree(char* arr, int* i)
{
    //对于树的创建是一个新的方法,要好好记着
    //此方法仍需要使用到递归
    //递归结束条件:当arr中的数据为#时,代表遇到的是NULL,此时需要返回NULL被存储
    if(arr[(*i)] == '#')
    {
        (*i)++;
        return NULL;
    }
    //当不为空时,开辟空间即可
    TreeNode* root = CreatTreeNode(arr[(*i)++]);
    root->left = CreatTree(arr, i);
    root->right = CreatTree(arr, i);

    //我们需要返回的是头结点
    return root;
}
//--------------------------------------------------------------------------------
void TreeInOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    TreeInOrder(root->left);
    printf("%c ", root->val);
    TreeInOrder(root->right);
}

int main() {
    //1.创建一个数组,使用数组接收传入的字符串
    char arr[100];//题目要求长度不超过100,所以这里可以直接写
    scanf("%s", arr);

    //2.其次就是使用结构体来接受这些数据
    //将数组中的数据挨个放到二叉树中
    int i = 0;
    TreeNode* root = CreatTree(arr, &i);

    //3.树创建完成之后,就是简单的中序遍历
    TreeInOrder(root);

    return 0;
}

9.二叉树选择题

9.1二叉树性质1

对于任意一颗二叉树,如果度为0的结点的个数为n0,度为2的结点的个数为n2,则有:n0 = n2+1

证明上述性质:
在这里插入图片描述
在这里插入图片描述

9.2二叉树性质2

对于一棵二叉树,假设它:
前序排列:EFHIGJK
中序排列:HFIEJKG
后序排列:HIFJKGE
前序排列首先访问的是根节点,后序排列最后访问的是根节点,中序访问中间访问的是根节点,可以根据根节点的位置推出左子树和右子树
在这里插入图片描述

9.3二叉树性质三

对于完全二叉树来说,它拥有的度为1的结点只能有0/1个:
当完全二叉树有2n个结点时,度为1的结点有1个
当完全二叉树有2n+1个结点时,度为1的结点有0个

9.4选择题

//二叉树基本性质选择题
1. 某⼆叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该⼆叉树中的叶⼦结点数为( )
//不是完全二叉树,399个结点,度为2的结点数为199,所以叶子结点个数 = 度为2的结点个数+1 = 200
A 不存在这样的⼆叉树
B 200//√
C 198
D 199

2.在具有 2n 个结点的完全⼆叉树中,叶⼦结点个数为( )
//完全二叉树,2n个结点,度为1的结点个数为1,假设度为2的结点个数为x
//则叶子结点个数为x+1,那么2*x+1+1 = 2n,求得x = n-1,那么叶子结点个数为n-1+1 = n
A n//√
B n + 1
C n - 1
D n / 2

3.⼀棵完全⼆叉树的结点数位为531个,那么这棵树的⾼度为( )
//完全二叉树,假设数的高度为h,那么结点数为2的h次方-1,2的10次方为1024
//2的9次方为512,512《531《1024,所以数的高度为10
A 11
B 10//√
C 8
D 12

4.⼀个具有767个结点的完全⼆叉树,其叶⼦结点个数为()
//完全二叉树,767个结点,偶数,度为1的结点数为1,设叶子结点数为x
//那么度为2的结点数为x-1,则有2x-1 = 767,所以x = 384
A 383
B 384//√
C 385
D 386

//链式二叉树遍历选择题
1.某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为( )
//这一题很简单,自己画图写出前序遍历即可
A ABDHECFG//√
B ABCDEFGH
C HDBEAFCG
D HDEBFGCA

2.⼆叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK; 中序遍历:HFIEJKG.则⼆叉树根结点为( )
//先序遍历先访问的是根节点,所以直接选A
A E//√
B F
C G
D H

3.设⼀课⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为____。
//后序遍历最后访问的是根节点,所以根节点为a,然后根据中序遍历画图即可
A adbce
B decab
C debac
D abcde//√

4.某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)
的序列为( )
//仍然是自己依据性质画图
A FEDCBA//√
B CBAFED
C DEFCBA
D ABCDEF

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

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

相关文章

Java-----二叉树

1.树型结构 1.1概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看 起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点: 1.有…

本地文件上传

java本地文件上传 1、FileController /*** author: yc* des: 文件接口* date: 2024/8/4 11:11*/ RestController RequestMapping("/file") public class FileController {Resourceprivate FileService fileService;PostMapping("/upload")public Respon…

智能交通(6)——DQN代码复现

伪代码 如算法描述,dqn即深度q网络和记忆池 初始化记忆池和可以容纳的数量N 动作价值函数Q使用随机权重进行初始化。 目标动作价值函数Q′也使用相同的权重进行初始化,即Q′Q。 循环训练M局 初始化和预处理观察到的状态 每局循环训练T步 采用e的概…

【Scene Transformer】scene transformer论文阅读笔记

文章目录 序言(Abstract)(Introduction)(Related Work)(Methods)(Scene-centric Representation for Agents and Road Graphs)(Encoding Transformer)(Predicting Probabilities for Each Futures)(Joint and Marginal Loss Formulation) (Results)(Discussion)(Questions) sce…

Linux|最佳命令行下载加速器

引言 无论是远程工作还是本地工作,我们经常需要从外部获取信息。在没有其他选择的情况下,使用命令行工具来获取这些信息是一个不错的选择。 本文[1]将介绍一些通过命令行下载内容时最常使用的工具。 Wget 我们首先介绍一个广受欢迎的工具 wget。它是一个…

使用Qt编译modbus

一.编译库文件 1. 创建library项目 2. 选择要配置的编译器 3. 把自动生成的源码都移除:(右键单击,选择 remove) 4 4. 导入库源码 把源码拷贝到项目目录下(.pro 文件所在的目录) 5. 修改 configure.js 文…

(计算机网络)物理层

目录 一.基本概念 二.基本术语 三.码元 四.多路复用技术 一.基本概念 1. 2. 3. 4. 5. 6. 7. 8. 9. 二.基本术语 1. 2. 3.早期--公用的电话网传输数据,网络上传的是模拟信号,调制解调器--将数字信号转化成模拟信号,最后,调制解…

Java: 线程安全问题的解决方案(synchronized)

发生原因 要想解决线程安全问题,那么我们首先得知道线程安全问题为什么会发生. 发生原因: 线程在操作系统中是"随机调度,抢占式执行的"[根本原因].多个线程,同时修改同一个变量修改操作不是"原子"的内存可见性问题指令重排序 解决方案 原因1和2,我们很…

htsjdk库FeatureCodec和Feature接口介绍

在 HTSJDK 库中,FeatureCodec 接口和 Feature 接口分别扮演不同的角色,用于处理基因组数据的不同方面。下面是这两个接口的区别和各自的功能: FeatureCodec 接口 主要功能 编码和解码:FeatureCodec 接口的主要职责是定义如何将数据从文件格式解码为 Java 对象(即 Featur…

【C语言】分支与循环(循环篇)——结尾猜数字游戏实现

前言 C语言是一种结构化的计算机语言,这里指的通常是顺序结构、选择结构、循环结构,掌握这三种结构之后我们就可以解决大多数问题。 分支结构可以使用if、switch来实现,而循环可以使用for、while、do while来实现。 1. while循环 C语言中…

[CP_AUTOSAR]_系统服务_DEM模块(三)功能规范之诊断事件定义

目录 1、诊断事件定义1.1、Event priority(事件优先级)1.2、Event occurrence(事件发生计数器)1.3、Event kind(事件类别)1.4、Event destination(故障内存)1.5、Diagnostic monitor…

2.MonggoDB是什么?

1. 不是什么? 要想知道MongoDB是什么,我们得先搞清楚它不是什么,首先它不是关系数据,不是像下面这样这种格式存储数据。 这个图展示了关系型数据库的常用存储方式,一个表格,里面存储了多行记录&#xff0…

Linux系统中的两个核心进程:`init`和`kthreadd`

文章目录 1 init 进程1.1 基本信息1.2 主要功能1.3 示例 2 kthreadd 进程2.1 基本信息2.2 主要功能2.3 示例 3 对比总结4 用户空间进程与内核线程4.1 用户空间进程特点 4.2 内核线程特点 5 对比总结6 结论参考链接封面 本文详细对比了Linux系统中的两个核心进程: i…

nvm 对node版本的控制

使用nvm切换Node.js版本的步骤如下 nvm list available // 显示可以安装的所有node.js的版本 如果出现空白 问题解决 经过查找nvm的文档,发现,对于中国用户而言,可以切换nodejs或npm的镜像地址来访问: nvm node_mirror https:…

软raid - - udev规则

一、什么是udev FROM AI: udev是Linux 2.6内核及以后版本中引入的一个设备管理框架,它取代了之前的devfs系统。udev以守护进程的形式运行,并且工作在用户空间而不是内核空间。它的主要功能是动态地创建和管理/dev目录下的设备节点,并且能够根…

SAP支出管理,企业成本控制的智能钥匙

在企业运营中,有效的支出管理是确保财务健康和提升竞争力的关键。SAP支出管理系统作为企业资源规划的核心组成部分,提供了一套全面的解决方案,帮助企业实现成本控制、风险管理和合规性监督。实现支出管理流程自动化,并主动管理更多…

蚂蚁笔试0511-编程题

解题思路: 记录0、正数、负数的个数,分类讨论。 解题思路: 有n个位置,每个位置有m个数,所以一共有m^n种情况,每种情况至少包含权值1,也就是全相等是一段,或者说是一个数形成的 从第二…

黑马Java零基础视频教程精华部分_11_面向对象进阶(3)

系列文章目录 文章目录 系列文章目录一、抽象类1、为什么要有抽象类?2、抽象方法3、抽象类4、抽象类和抽象方法定义格式5、注意事项 二、接口1、为什么会有接口?2、接口和抽象类的异同3、接口的定义和使用4、接口中成员的特点5、接口和类之间的关系6、实…

机器学习第五十周周报 CGNN

文章目录 week50 CGNN摘要Abstract0. 概述1. 题目2. Abstract3. 网络结构3.1 状态更新网络3.2 method 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程 5. 结论6.相关代码CompositeLGNNCompositeGNNcomposite-graph-class小结参考文献 week50 CGNN 摘要 本周阅读了题为Co…

【题解】189. 轮转数组(数组、数学、双指针)

https://leetcode.cn/problems/rotate-array/description/?envTypestudy-plan-v2&envIdtop-interview-150 class Solution { public:void rotate(vector<int>& nums, int k) {k k % nums.size(); // 注意k要取一下模reverse(nums.begin(), nums.end()-k);rev…