树的子结构判断

【题目】输入两棵二叉树A和B,判断B是不是A的子结构。


【分析】

典型的二叉树问题。
判断两个二叉树的所属关系,其实还是要从二叉树的结构特点出发,二叉树由根节点和左右孩子构成,如果一个二叉树是另一个的子树,说明这个二叉树根节点,左右孩子必然存在于另一个二叉树中,例如:

这里写图片描述

观察上图,发现第二个二叉树明显是第一个二叉树的子结构,首先,看根节点,8,第一棵树根节点为8,等于第二棵二叉树,观察其左右孩子结构,如果一致,说明所属关系成立,但是根结点为8的第一棵二叉树左孩子是8,第二棵二叉树左节点却是9,所以继续查看观察的第一棵二叉树的左子树,左子树第一个根节点就是8,所以看它的左右孩子,左孩子是9,等于第二棵二叉树,所以再看右孩子,是2,结构完全相等,说明第二棵二叉树是第一棵二叉树的子结构成立。

在判断过程中,很明显用递归方法比较简单,递归判断二叉树A的根结点和二叉树B根节点是否相同,找到相同的后,再递归判断左右孩子结构是否一致。


【示例代码】

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

#define false 0
#define true 1
typedef struct BinaryTreeNode
{
    char data;
    struct BinaryTreeNode *left;
    struct BinaryTreeNode *right;
}Node;
//按照前序输入二叉树中结点的值
//构建二叉树
void create(Node **T)
{
    char ch;
    scanf("%c",&ch);
    if(ch == '#')
        *T = NULL;
    else
    {
        *T = (Node *)malloc(sizeof(Node));
        (*T)->data = ch;
        create(&(*T)->left);
        create(&(*T)->right);
    }
}

bool doestree1havetree2(Node *root1, Node *root2)
{
    if(root2 == NULL)
        return true;

    if(root1 == NULL)
        return false;

    if(root1->data != root2->data)
        return false;
    return doestree1havetree2(root1->left,root2->left) &&doestree1havetree2(root1->right, root2->right);
}

bool hassubtree(Node *root1, Node *root2)
{
    bool result = false;

    if(root1 != NULL && root2 != NULL)
    {
        if(root1 ->data == root2->data)
            result = doestree1havetree2(root1,root2);
        if(!result)
            result = hassubtree(root1->left, root2);
        if(!result)
            result = hassubtree(root1->right, root2);
    }

    return result;
}

void main()
{
    Node * root1 = NULL;
    Node * root2 = NULL;

    printf("二叉树1:\n");
    create(&root1);
    printf("\n");


    printf("二叉树2:\n");
    getchar();
    create(&root2);
    printf("\n");

    printf("二叉树2是在二叉树1子构吗:\n");
    bool r = hassubtree(root1, root2);
    if(r == false)
        printf("no, root2 is not root1's subtree!\n");
    if(r == true)
        printf("yes, root2 is root1's subtree!\n");
    printf("\n");
}

【测试结果】

这里写图片描述

按照前序遍历创建二叉树1和2
在测试代码时,出现了问题,创建了二叉树1之后,二叉树2无法创建,究其原因是因为在创建链表过程中忽略了一个问题,在我们输入字符时都是先进入缓存区,scanf访问缓存得到数据,当我们把889##24##7##7##输完后输入回车,scanf读到回车符,就知道,输入完毕了,但是此时缓存区回车字符还在,当下一次输入89##2##时,先读取的是缓存区的回车符,然后才读89。。。这些数据,所以在建立树2时,清理缓存, getchar()清除缓冲区单一字符输入时scanf(“%c’,&a[i]);的换行符’\n’,除了getchar以外还有 fflush()是清除文件缓冲区,fflush(stdin); 如果没有这句,则stdio中还有数据,比如回车符,除此之外, scanf(“\n%d”,&c)也能达到效果,但不是清理缓存,而是自动将回车符读取了,scanf本来就是按照格式化的输入,所以当第一个输入为回车时它自动读取了,就不用清理缓存了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值