当前位置: 首页 > article >正文

二叉树相关|单值二叉树|相同的树|对称二叉树|前序遍历|中序遍历|后序遍历|另一棵树的子树|二叉树遍历(C)

965. 单值二叉树


判断一棵树节点的值是不是都相等
用分治的思想解决
如果当前子树根等于左子树的根,等于右子树的根,可以认为这三个节点的值相等
![[Pasted image 20241101092400.png]]

如果当前三个节点没问题,就递归遍历左子树,如果还相等,可以得出5个节点都是相等的
如果递归到空树,就返回

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);
}

![[Pasted image 20241101093448.png]]

是前序
判断的时候,先判断自己,再判断左右

100. 相同的树


![[Pasted image 20241101140000.png]]

拆解子问题
把树分成三个部分

  1. 判断根和根
  2. 判断左子树和左子树
  3. 判断右子树和右子树
    但凡有一个不相等就返回false
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);
}

101. 对称二叉树


![[Pasted image 20241101135936.png]]

拆解子问题
判断树的两个子树是否相等

  1. 判断左子树的根和右子树的根
  2. 判断左子树的左子树和右子树的右子树
  3. 判断左子树的右子树和右子树的左子树
    如果有一个不相等就返回false
bool isSymmetricTree(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 isSymmetricTree(p->left, q->right)
        && isSymmetricTree(p->right, q->left);
}
  
bool isSymmetric(struct TreeNode* root)
{
    return isSymmetricTree(root->left, root->right);
}

144. 二叉树的前序遍历


前序遍历二叉树,把前序遍历的结果存到一个数组里面

遍历的时候需要定义一个数组的下标来存数据,因为每次递推,每个函数栈帧都会有一个i,形参不会影响实参,所以i会出现问题
所以定义一个局部变量,通过传地址来解决这个问题
不能用静态变量,否则每次调用函数都需要把下标置空

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

void preorder(struct TreeNode* root, int* a, int* pi)
{
    if (root == NULL)
        return;
  
    a[(*pi)++] = root->val;
    preorder(root->left, a, pi);
    preorder(root->right, a, pi);
}
  
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int n = TreeSize(root);
    int* a = (int*)malloc(sizeof(int)*n);
  
    int i = 0;
    preorder(root, a, &i);
  
    *returnSize = n;
    return a;
}

这里需要返回数组的大小,通过返回二叉树的节点个数来实现

94. 二叉树的中序遍历


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

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

int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
    int n = TreeSize(root);
    int* a = (int*)malloc(sizeof(int)*n);
    
    int i = 0;
    inorder(root, a, &i);
    
    *returnSize = n;
    return a;
}

145. 二叉树的后序遍历


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

void postorder(struct TreeNode* root, int* a, int* pi)
{
    if (root == NULL)
        return;

    postorder(root->left, a, pi);
    postorder(root->right, a, pi);
    a[(*pi)++] = root->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int n = TreeSize(root);
    int* a = (int*)malloc(sizeof(int)*n);

    int i = 0;
    postorder(root, a, &i);

    *returnSize = n;
    return a;
}

572. 另一棵树的子树


一棵树是不是另一棵的子树
先判断根节点,如果根节点相等再判断左子树和右子树
![[Pasted image 20241101153002.png]]

让左边树的每一棵子树都跟右边的子树比较一遍

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 (root->val = subRoot->val)
    {
        if (isSameTree(root, subRoot))
            return true;
    }

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

最后返回bool值,左边比一下,右边比一下,如果左边找到了就不需要再比右边,直接返回上一层
如果都没有找到false || false还是false

二叉树遍历_牛客题霸_牛客网


先序遍历字符串,空树的位置用#替代
用前序遍历的方式构建二叉树
遇到空树返回,不再构建
再中序遍历,输出遍历结果

如何通过遍历的结果恢复出树

ABC##DE#G##F###
下标从头依次往后遍历

遇到A,先构建A,再往后遍历,递归构建A的左
![[Pasted image 20241101155058.png]]

下标到C,再构建B的左
![[Pasted image 20241101155138.png]]

C构建完再++下标,C的左边是空,空树直接返回连接到C的左边
![[Pasted image 20241101155304.png]]

C的左边构建好,再构建C的右边,++下标,右边也是一棵空树
![[Pasted image 20241101155354.png]]

C构建好之后,C返回,连接到B的左边
![[Pasted image 20241101155438.png]]

B的左边构建好之后,++下标,构建B的右边
![[Pasted image 20241101155526.png]]

++发现是E,构建D的左边

![[Pasted image 20241101155827.png]]

全部遍历完毕

#include <stdio.h>
#include <stdlib.h>
typedef struct BinaryTreeNode
{
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
    int val;
}BTNode;
  
BTNode* CreateTree(char* str, int* pi)
{
    if (str[*pi] == '#')
    {
        ++(*pi);
        return NULL;
    }
  
    BTNode* root = (BTNode*)malloc(sizeof(BTNode));
    root->val = str[*pi];
    (*pi)++;
  
    root->left = CreateTree(str, pi);
    root->right = CreateTree(str, pi);
  
    return root;
}
  
void Inorder(BTNode* root)
{
    if (root == NULL)
        return;
  
    Inorder(root->left);
    printf("%c ", root->val);
    Inorder(root->right);
}
  
int main() {
    char str[100];
    scanf("%s", str);
  
    int i = 0;
    BTNode* root = CreateTree(str, &i);
    Inorder(root);
  
    return 0;
}

http://www.kler.cn/a/383297.html

相关文章:

  • 在 CentOS 系统上安装 ClickHouse
  • C语言项目 天天酷跑(上篇)
  • Logback日志框架中的继承机制详解
  • 查询 MySQL 默认的存储引擎(SELECT @@default_storage_engine;)
  • 单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
  • Docker 部署 plumelog 最新版本 实现日志采集
  • 【后端】登录页面的 <验证码> 操作
  • Linux 进程间通信 共享内存_消息队列_信号量
  • 用Dify搭建AI知识库
  • ORACLE数据库查询当前安装的语言是哪一种?
  • Python反射API:面向对象编程的“魔法镜”
  • 大语言模型(LLM)量化基础知识(一)
  • 后端SpringBoot及vue proxyTable解决跨域
  • 机器学习与AI|如何利用数据科学优化库存周转率?
  • 前端入门一之HTML知识讲解
  • HarmonyOS-消息推送
  • 使用vue添加网站结构化标记schema
  • Python 操作数据库:读取 Clickhouse 数据存入csv文件
  • Java之字符串分割转换List
  • faiss用于大数据量的向量检索
  • vm虚拟机中添加网卡却在network-scripts文件找不到,解决方法
  • vue中的nextTick() - 2024最新版前端秋招面试短期突击面试题【100道】
  • IDEA2024下安装kubernetes插件并配置进行使用
  • Spring源码(十一):Spring MVC之DispatchServlet
  • WPF+MVVM案例实战(二十)- 制作一个雷达辐射效果的按钮
  • Ubuntu 安装Nvidia 显卡驱动