【二叉树】—— 算法题

一、单值二叉树

        题目要求:判断二叉树是不是单值二叉树(就是所以节点的值都相等)。

思路:

        利用二叉树的递归思想,判断每一个节点值与其左右子节点的值是否相等,如果遇到空节点,就返回true(说明每一个节点值都相等);如果遇到节点的值与其左右节点值不相等就返回false;如果该节点的值与其左右子节点的值都相等,就接着递归该节点的左右子树。

代码如下:

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

        判断两个二叉树是否相等

思路:

        同时遍历两个二叉树,如果遍历到两个二叉树节点同时为空,就说明这两个二叉树相同;如果其中一个为空而另一个不为空,就说明两个二叉树不相同;如果遍历过程中,遇到两个二叉树节点的值不相等,则两个二叉树不相同。

简单分析一下:

        同时遍历这两个二叉树

        两个二叉树节点都不为空且值相等,继续遍历其左子树

        两个二叉树节点都不为空且值相等,继续遍历其左子树

        两个二叉树节点都为空,返回true

        先遍历二叉树是2节点的右节点,也为空,这里直接跳过了。

        这里回退到1这个节点,接下来遍历1的右子树

        遍历到节点都不为空,且值相等,继续遍历 (这因为3的左右节点都为空,就一步带过)

        遍历结束,没有遇到一个节点为空一个节点不为空或者值不相等的情况,就返回true。

代码如下:

typedef struct TreeNode TreeNode;
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);
}

        2.2、对称二叉树

        

        判断二叉树是否是对称二叉树,这里还是实现与上题相同的树类似的思路。

思路:

        利用相同的树的方法,判断二叉树根节点的左右子树是否对称(判断对称直接判断一个节点的左子树和另一个节点的右子树是否相等即可)。

代码如下:

typedef struct TreeNode TreeNode;
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->right) && isSameTree(p->right, q->left);
}
bool isSymmetric(struct TreeNode* root) {
    return isSameTree(root->left,root->right);
}

        2.3、另一颗树的子树

        判断一个树是否是另一个树的子树

思路:

        还是利用相同二叉树的方法,判断二叉树及其左右子树中是否存在与另一棵树相同的树。

代码如下:

typedef struct TreeNode TreeNode;
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;
    }

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

三、二叉树的遍历(前序中序后序

        本题要求,前序遍历二叉树,并且返回前序遍历的结果(以数组方式返回),并且还用通过指向修改数据个数。

思路:

        这里首先求二叉树的节点个数;然后动态申请内存来存储数据并且用来最后返回数组首元素地址;最后就是将数据存储到数组当中了,使用前序遍历。

代码如下:

typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    return TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _preorderTraversal(TreeNode* root,int* arr,int* pi)
{
    if(root==NULL)
    {
        return ;
    }
    arr[(*pi)++]=root->val;
    _preorderTraversal(root->left,arr,pi);
    _preorderTraversal(root->right,arr,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {

    // 求出二叉树的节点个数
    *returnSize =TreeSize(root);
    // 动态申请空间大小
    int* returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    // 前序遍历
    int i=0;
    _preorderTraversal(root,returnArr,&i);
    return returnArr;
}

中序和后序遍历与其思路一样这里直接看代码。

中序遍历

 typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    return TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _inorderTraversal(TreeNode* root,int* arr,int* pi)
{
    if(root==NULL)
    {
        return ;
    }
    _inorderTraversal(root->left,arr,pi);
    arr[(*pi)++]=root->val;
    _inorderTraversal(root->right,arr,pi);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {

    // 求出二叉树的节点个数
    *returnSize =TreeSize(root);
    // 动态申请空间大小
    int* returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    // 中序遍历
    int i=0;
    _inorderTraversal(root,returnArr,&i);
    return returnArr;
}

后序遍历

  typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    return TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _postorderTraversal(TreeNode* root,int* arr,int* pi)
{
    if(root==NULL)
    {
        return ;
    }
    _postorderTraversal(root->left,arr,pi);
    _postorderTraversal(root->right,arr,pi);
    arr[(*pi)++]=root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {

    // 求出二叉树的节点个数
    *returnSize =TreeSize(root);
    // 动态申请空间大小
    int* returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    // 中序遍历
    int i=0;
    _postorderTraversal(root,returnArr,&i);
    return returnArr;
}

四、二叉树的构建和遍历

        创建二叉树,并且中序遍历。

因为这里题目说先序遍历字符串(我们根据这个来构建二叉树),本题要求写全部代码。

思路:

        先创建字符数组,根据输入的字符串进行创建二叉树,创建完成以后再进行中序遍历输出即可。

代码如下:

#include <stdio.h>
#include<stdlib.h>
typedef struct BinaryTreeNode
{
    char str;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;

BTNode* BuyNode(char x)
{
    BTNode* newnode=(BTNode* )malloc(sizeof(BTNode));
    newnode->str=x;
    newnode->left=newnode->right=NULL;
    return newnode;
}
BTNode* CreatTree(char* str,int* pi)
{
    if(str[*pi]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode* root=BuyNode(str[(*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->str);
    InOrder(root->right);
}
int main() {
    char str[100];
    scanf("%s",str);
    //根据字符创建二叉树
    int i=0;
    BTNode* root=CreatTree(str, &i);
    InOrder(root);
    return 0;
}

感谢各位大佬支持并指出问题,

                        如果本篇内容对你有帮助,可以一键三连支持以下,感谢支持!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值