树的子结构判断

来源:互联网 发布:淘宝1元拍卖可信吗 编辑:程序博客网 时间:2024/05/29 08:36

【题目】输入两棵二叉树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 1typedef 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
原创粉丝点击