【数据结构和算法初阶(c语言)】二叉树系列oj题目图文详解

目录

1.单值二叉树

2.判断两颗二叉树是否相同

3.二叉树的前序遍历

接口了解 

4.判断一棵树是不是另外一棵树的子树

5.判断一棵树是不是对称二叉树

6.二叉树遍历


1.单值二叉树

. - 力扣(LeetCode)

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false

解题思路:

先判断根和它的左右子树相等不相等,都相等再次判断左右子树和他们的孩子是否相等。(递归的思想)先判断根再判断左右子树属于前序遍历。

题解代码:

bool isUnivalTree(struct TreeNode* root) {

    //如果根为空,这里根据示例1可以返回空

    if(root ==NULL)

    {

        return true;

    }

    //根节点不为空了,现在就来看一下左右孩子的值等不等于根

    if(root->left  &&root->left->val != root->val)

    {

           return false;

    }

     //首先要判断左右孩子有没有,然后再判断两个值是否相等,左子树值与根相等,右子树值与根相等,判定三个节点的值相等。但是如果是判断值相等作为判断条件这里不能直接返回true,返回false是比较好的处理方式

     if(root->right && root->right->val != root->val)

     {

            return false;

     }


 

     //当上述都没有进入说明这一次的根左右子树是相等的,就去下一层

     return isUnivalTree(root->left)&&isUnivalTree(root->right);

     //只要一个返回false就返回false,第一个返回false就不会执行第二个

   

}

我们来看一下例子和代码的递归展开图对比:红色是向下执行,绿色是返回

2.判断两颗二叉树是否相同

. - 力扣(LeetCode)

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

 

解题思想:拆分为子问题,根比较,左子树比较,再右子树比较。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p==NULL&&q==NULL)
    {
        return true;//如果两个都为空,返回真,这是处理到最后节点的时候,也是从根开始的比较,每一次递归的节点都可以看做是这次比较的根
        
    }
    if(p==NULL||q==NULL)
    {
        return false;//p,q当中至少一个为空的情况,这里就是可以判断一个树有这个节点而另外一棵树没有这个节点的情况,那么这两颗树就是不一样的
    }
    //接下来判定值
    if(p->val!= q->val)
    {
        return false;//判断值相等作为条件会麻烦一些,判断值不等
    }
    //根比较完就开始比较树的左右子树
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);//左右子树返回一个folse整体就为假
}

 

3.二叉树的前序遍历

. - 力扣(LeetCode)

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

我们先看一下这个题目给的接口,补充一些接口了解内容

接口了解 

 

第一:题目要求将打印的结果存在一个数组中,这个数组必须是malloc开辟,但是不需解题的人释放,调用者会去释放。

第二:关于returnsize:这个参数是一个记录数组大小的值,就是说这个函数被调用后我们应该给调用者返回数组的指针,同时也要让调用者能够拿到这个数组的大小方便调用者去遍历这个数组,但是,一个函数是不能够有两个返回值的,所以,这里定义一个int * 类型的指针,外部传入一个变量的地址,通过解引用修改,就可以改变调用者传递过来的这个值,然后调用者可以拿到这个数组的大小。

int Treesize(struct TreeNode* root)
 {
    return root==NULL ? 0: Treesize(root->left)+Treesize(root->right)+1;
 }
 void perorder(struct TreeNode* root,int* a,int* i)
 {
    if(root==NULL)
    {
        return;
    }
    //不为空就将值放入数组里面
    a[(*i)++] = root->val;
    
    perorder(root->left,a,i);//遍历左树,这里传值1注意i已经是指针
    perorder(root->right,a,i);//遍历右树
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //首先开辟数组方便后面存储
    int n = Treesize(root);
    int* a = (int *)malloc(sizeof(int)*n);
    //这里我们的空间开辟多大,不能盲目指定,开辟大了浪费空间,开辟小了不够,relloc多了会导致内存之间空隙太多,也不是很好,这里我们就根据数的大小来确定所以我们先求一下树的大小。
    //进行前序遍历
    int i =0;
    perorder(root,a,&i);//这里传数组下标使用的是传地址,防止递归过程中有时不会发生下标值的改变造成失误

    *returnSize= n;//返回数组的大小
    return a;//返回a
}

4.判断一棵树是不是另外一棵树的子树

. - 力扣(LeetCode)

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

思想:先把根作为一颗树和右边比较看是不是一颗树,因为,相同的树也是子树,不是在和左右子树进行比较 

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p==NULL&&q==NULL)
    {
        return true;//如果两个都为空,返回真,这是处理到最后节点的时候,也是从根开始的比较,每一次递归的节点都可以看做是这次比较的根
        
    }
    if(p==NULL||q==NULL)
    {
        return false;//p,q当中至少一个为空的情况,这里就是可以判断一个树有这个节点而另外一棵树没有这个节点的情况,那么这两颗树就是不一样的
    }
    //接下来判定值
    if(p->val!= q->val)
    {
        return false;//判断值相等作为条件会麻烦一些,判断值不等
    }
    //根比较完就开始比较树的左右子树
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);//左右子树返回一个folse整体就为假
}

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

// bool ret = isSubtree(root->left,subRoot);
// if(ret)
// {
//     return true;
// }
// ret = isSubtree(root->right,subRoot);
// if(ret)
// {
//     return true;
// }
// return false;
return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);

}

5.判断一棵树是不是对称二叉树

. - 力扣(LeetCode)

 给你一个二叉树的根节点 root , 检查它是否轴对称。

解题思想:先看一下根不为空,就判断左右有没有,判断左右值相等与否在判断左子树的左边与右子树的右边,判断左子树的右边和右子树的左边

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) {
//思想:根和根比较,左子树的左边和右子树的右边进行比较,左子树的右边和右子树的左边进行比较2
if(root == NULL)
{
    return true;
}
//根不等于空就要比较一下左子树和右子树,左子树的左边和右子树的右边是否相等,比较左子树的右边和右子树的左边
//由于后续递归不涉及这棵主树的根,所以单独使用一个递归函数
return isSymmetricTree(root->left,root->right);
    
    
}

 

6.二叉树遍历

解题:

 

#include <stdio.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
    BTDataType val;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;
 
BTNode* CreatTree(char* str ,int*pi)
{
    if(str[*pi]=='#')
    {
        //如果此时字符为#,这个点就是空,不用申请节点
        (*pi)++;
        return NULL;
 
    }
    //不为空就申请节点
    BTNode* root = (BTNode*)malloc(sizeof(BTNode)*1);
    root->val = str[*pi];
    (*pi++);
    //然后递归连接左右子树
    root->left = CreatTree(str,pi);
    root->right= CreatTree(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* str2 = CreatTree(str,&i);
    //中序遍历
    Inorder(str2);
    return 0;
}

 

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值