【初级数据结构】二叉树OJ题

二叉树OJ题总结

1、平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1

示例:

image-20230114215739662 image-20230114215758491

我选择了自底向上递归的做法,类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 −1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。

int height(struct TreeNode* root) 
{
    if (root == NULL) 
    {
        return 0;
    }
   
    int leftHeight = height(root->left);
    int rightHeight = height(root->right);

    if (leftHeight == -1 || rightHeight == -1 || fabs(leftHeight - rightHeight) > 1) //此语句用来判断当前结点为根子树是否平衡 
    {
        return -1;//不平衡就返回-1
    } 
    else 
    {
        return fmax(leftHeight, rightHeight) + 1;
    }
}

bool isBalanced(struct TreeNode* root) 
{
    return height(root) >= 0;
}

2、前序遍历

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

示例:

image-20230114221325320

image-20230114221344238

之前就介绍过前序遍历,是按照根->左->右的顺序来遍历

我这道题选择了迭代的方式来做

首先明确迭代的含义,就是重复反馈来逼近结果

这道的思路就是利用迭代遍历模拟了栈的存储

int* preorderTraversal(struct TreeNode* root, int* returnSize) 
{
    int* res = malloc(sizeof(int) * 2000);
    *returnSize = 0;
    if (root == NULL) 
    {
        return res;
    }

    struct TreeNode* stk[2000];

    struct TreeNode* node = root;

    int stk_top = 0;

    while (stk_top > 0 || node != NULL) 
    {
        while (node != NULL) 
        {
            res[(*returnSize)++] = node->val;
            stk[stk_top++] = node;
            node = node->left;
        }
        node = stk[--stk_top];
        node = node->right;
    }
    return res;
}

3、翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例:

image-20230114223252782 image-20230114223307563

看起来有点麻烦,实际上我们可以从小规模的树开始思考如何翻转

我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

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

    struct TreeNode* left = invertTree(root->left);
    struct TreeNode* right = invertTree(root->right);

    root->left = right;
    root->right = left;

    return root;
}

4、对称二叉树

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

示例:

image-20230114223707024 image-20230114223720584

判断一个树是否对称,首先要判断左右孩子是否对称相等,还需要判断左孩子的左子树是否和右孩子的右子树对称,左孩子的右子树是否和右孩子的左子树对称

bool compare(struct TreeNode *left,struct TreeNode *right)
{
    if(left == NULL && right == NULL)
        return true;
    if(left == NULL || right == NULL)//上边的语句已经排除了同时为NULL的可能性
        return false;
    if(left->val != right->val)
        return false;
    return compare(left->left,right->right) && compare(left->right,right->left);
}

bool isSymmetric(struct TreeNode* root)
{
    if(root == NULL)
        return true;
    return compare(root->left,root->right);
}

5、子树问题

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

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

示例:

image-20230114224147629 image-20230114224205572

判断t是否为s的子树,需要判断t是否和s的某一个子树相同,所以此题就是判断两棵树是否相同的逻辑。

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

6、二叉树遍历

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

示例:

image-20230114224413270

这道题的解题思路就是,在先序遍历的过程中构建每一个节点

#include<stdio.h>
#include<stdlib.h>

typedef struct BTNode
{
    char val;
    struct BTNode* left;
    struct BTNode* right;
}BTNode;

struct BTNode* BinaryTreeCreate(char* p,int* k)
{
    if(p[*k] == '#')
    {
        (*k)++;
        return NULL;
    }
    
    BTNode* tmp=(BTNode*)malloc(sizeof(BTNode));
    if(tmp == NULL)
    {
        exit(-1);
    }
    tmp->val=p[*k];
    (*k)++;

    tmp->left=BinaryTreeCreate(p,k);
    tmp->right=BinaryTreeCreate(p,k);
    
    return tmp;
    
}
void Inorder(struct BTNode* root)
{
    if(root == NULL)
        return;
    Inorder(root->left);
    printf("%c ",root->val);
    Inorder(root->right);
    
}

int main()
{
    char c[101];
    while(scanf("%s",c) != EOF)
    {
        int k=0;
        BTNode* root=BinaryTreeCreate(c,&k);
        Inorder(root);
    }
    
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值