【数据结构】二叉树OJ题

 😽PREFACE
🎁欢迎各位→点赞👍 + 收藏⭐ + 评论📝
📢系列专栏:数据结构
🔊本专栏主要更新的是数据结构部分知识点
💪种一棵树最好是十年前其次是现在

目录

1.单值二叉树 

2.相同的树

3.前序遍历

4.另一棵树的子树

5.二叉树遍历


1.单值二叉树 

题目链接:力扣

 代码演示:

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.相同的树

题目链接:力扣

  • 思路:首先如果p,q都是空,那么满足条件,直接返回true。如果其中一个为空,则返回false;如果两个都不为空,这个时候还应该分两种情况,如果对应的值不等,那么返回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);
    }

3.前序遍历

题目链接:力扣

  • 思路:在上篇文章我们已经实现了前序遍历,而此题明显就是让我们去模拟实现,题中条件明确指出要动态开辟一块数组来存放数据,关键是开辟多大空间呢?所以这里用到第一个辅助函数——求节点个数函数(TreeSize)。接下来就是依次递归分治思想,但是我们发现了一个致命的缺陷,就是每次递归到主函数时都要malloc,这样是十分消耗栈帧的,因此还需要构造第二个辅助函数专门用于递归。
  • 注意点:传节点个数时,一定要传地址。因为每次递归都会建立栈帧,递归完就会销毁,无法保存。此外,*returnSize是要返回数组元素的,返回给调用者。
  • 代码演示:
    //写一个函数用于求出二叉树节点的个数,方便后面malloc
    int TreeSize(struct TreeNode* root)
    {
        return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
    }
    
    //写一个专门用于递归的函数,防止用主函数递归时每次都要malloc
    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){
        //接受节点个数
        *returnSize=TreeSize(root);
        //动态开辟数组
        int* a=(int*)malloc(*returnSize*sizeof(int));
        int i=0;
        //i一定要传地址,因为每次递归都会建立栈帧,递归完之后就会销毁
        preorder(root,a,&i);
        return a;
    }

4.另一棵树的子树

题目链接:力扣

  • 思路:遍历左边树的每一个节点使其作为子树的根,跟右树的子树都比较一下,此时就可以cv之前写过的函数(isSameTree) ,用来比较两棵树是否相同,依次比较,如果是子树,则返回true
  • 代码演示:
    //判断两棵树是否相同
    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;//是子树就返回true
        }
        return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
    }
     

5.二叉树遍历

题目链接:二叉树遍历_牛客题霸_牛客网

  •  思路:首先本题要求根据我们输入的字符串将其构建成树,再按照中序的遍历方式输出。例如:
  •  构造时要按照先序遍历,递归过程如下:首先遇到a,不是‘#’,接着向下构造左子树b,同理再向下构造左子树c,这个时候遇到了‘#’。则回溯到c,再来构造c的右子树,结果又遇到‘#’,因此再向上回溯到b,此时再构造b的右子树,接着同理……
  • 如果已经创建好二叉树的结构了,下面只需要按照中序遍历打印出来即可。
  • 代码演示:
    //创建二叉树结构
    struct TreeNode
    {
        struct TreeNode* left;
        struct TreeNode* right;
        char val;
    };
    
    //创建节点,先序结构创建
    struct TreeNode* CreatTree(char* a,int* pi)
    {
        if(a[*pi]=='#')
        {
            (*pi)++;
            return NULL;
        }
    
        struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    
        root->val=a[(*pi)++];
        root->left=CreatTree(a,pi);
        root->right=CreatTree(a,pi);
        return root;
    }
    
    //中序输出
    void InOrder(struct TreeNode* root)
    {
        if(root==NULL)
        {
            return ;
        }
        InOrder(root->left);
        printf("%c ",root->val);
        InOrder(root->right);
    }
    
    
    int main() {
        char a[100];
        scanf("%s",a);
        int i=0;
        struct TreeNode* root=CreatTree(a,&i);
        InOrder(root);
        return 0;
    }

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值