数据结构初阶--二叉树OJ1

二叉树的最大深度

先来看题目描述

思路分析

题目想让我们求一颗二叉树的最大深度,我们就分别从左子树和右子树往下找,并每次都返回左子树和右子树中的较大值。因为父节点也算一层,所以还要在算出的最大值的基础上再加1.

代码实现

代码如下

int maxDepth(struct TreeNode* root){
    if(root==NULL)
    return 0;
    return fmax(maxDepth(root->left),maxDepth(root->right))+1;

}

相同的树

题目如下

思路分析

大致思路就是左子树和左子树比较,右子树和右子树比较,如果都为空,说明走完了,则返回true。只要两个不相等或一个为空一个不为空(要单独拿出来,防止访问空指针),就返回false。

代码实现

代码如下

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

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

单值二叉树

题目如下

思路分析

这道题我们惯性思维可能都会先想到左右孩子相比较看是否相等,但这样其与父节点的关系就切断了,我们还要保证其与父节点也相等才对。所以正确思路是每次比较左孩子与父节点,右孩子与父节点是否相等。(注意先判断有没有左右孩子,以防访问空指针)。

代码实现

代码如下

bool isUnivalTree(struct TreeNode* root){
    if(root==NULL)
    return true;


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

}

二叉树的前序遍历

先来看题目描述(注意答案是放在一个数组中的

思路分析

这道题的重点在于我们要有返回值,而返回值就是数组长度,即二叉树的节点个数,难点在于要将节点的值放入一个动态开辟的数组当中去,这里访问数组下标就有别于普通访问了,求节点个数没有什么难度,这里就不细讲了,我们把代码主要分为三个主体:计算大小的函数,开辟数组并返回的主函数和将节点的值放入数组的函数,因为我们要对数组在另一个函数里访问,所以在访问下标是要传下标的地址

代码实现

代码实现如下


int TreeSize(struct TreeNode* root)
{
    if(root==NULL)
    return 0;

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

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

    p[(*pi)++]=root->val;
    _preorder(root->left,p,pi);
    _preorder(root->right,p,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize=TreeSize(root);
    int* p=(int*)malloc(sizeof(int)*(*returnSize));
    
    int i=0;
    _preorder(root,p,&i);
    return p;
}

翻转二叉树

先来看题目描述

思路分析


大致思路就是先交换左右孩子,然后递归左子树,然后右子树,这样就能实现翻转二叉树了,图解如上。

代码实现

代码实现如下

struct TreeNode* invertTree(struct TreeNode* root){
    if(root==NULL)
    return NULL;

    struct TreeNode* temp=root->left;
    root->left=root->right;
    root->right=temp;

    invertTree(root->left);
    invertTree(root->right);
    return root;

}

对称二叉树

先来看题目描述

思路分析

因为我们要探究的是是否为轴对称,所以我们首先第一步要将其分成左右两个子树,后续的递归操作我们再在另一个函数中去实现,注意比较对象是左子树的左孩子,右子树的右孩子还有判断条件。

代码实现

代码实现如下

 bool _isSymmetric(struct TreeNode* leftroot,struct TreeNode* rightroot)
 {
     if(leftroot==NULL&&rightroot==NULL)
     return true;
     if(leftroot==NULL&&rightroot!=NULL)
     return false;
     if(leftroot!=NULL&&rightroot==NULL)
     return false;
     if(leftroot->val!=rightroot->val)
     return false;

     return _isSymmetric(leftroot->left,rightroot->right)
     &&     _isSymmetric(leftroot->right,rightroot->left);


 }
bool isSymmetric(struct TreeNode* root){
    if(root==NULL)
    return true;

    struct TreeNode* leftroot=root->left;
    struct TreeNode* rightroot=root->right;
    return _isSymmetric(leftroot,rightroot);

}

另一棵树的子树

题目描述如下

思路分析

这道题的主体思路是遍历root的所有节点,并每次与subroot进行匹配,这个操作在另一个函数中实现,逐个比较subroot和当前作为根节点的root.除了要注意比较函数中的中止递归的条件,还要注意主函数中,如果root为空了,说明遍历完了还没有找到匹配的子树,则返回false。

代码实现

代码如下

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

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(root==NULL){
        return false;
    }
    return compare(root,subRoot)||isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷吃橙子的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值