• C/C++数据结构——树的同构(二叉树)


    题目描述

    给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
    在这里插入图片描述
    在这里插入图片描述
    现给定两棵树,请你判断它们是否是同构的。

    输入格式:

    输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

    输出格式:

    如果两棵树是同构的,输出“Yes”,否则输出“No”。

    输入样例1(对应图1):

    8
    A 1 2
    B 3 4
    C 5 -
    D - -
    E 6 -
    G 7 -
    F - -
    H - -
    8
    G - 4
    B 7 6
    F - -
    A 5 1
    H - -
    C 0 -
    D - -
    E 2 -

    输出样例1:

    Yes

    输入样例2(对应图2):

    8
    B 5 7
    F - -
    A 0 3
    C 6 -
    H - -
    D - -
    G 4 -
    E 1 -
    8
    D 6 -
    B 5 -
    E - -
    H - -
    C 0 2
    G - 3
    F - -
    A 1 4

    输出样例2:

    No

    代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

    解题代码

    #include
    #include
    typedef struct Tree{
        char data;
        int l,r;
    }tree;
    tree treeA[11],treeB[11];
    int initTree(int n,tree root[])
    {
        char a;
        int num[11];
        getchar();
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++){
            scanf("%c",&root[i].data);
            getchar();
            scanf("%c",&a);
            getchar();
            if(a=='-'){
                root[i].l=-1;
            }else{
                root[i].l=a-'0';
                num[root[i].l]=1;
            }
            scanf("%c",&a);
            getchar();
            if(a=='-'){
                root[i].r=-1;
            }else{
                root[i].r=a-'0';
                num[root[i].r]=1;
            }
        }
        int i;
        for(i=0;i<n;i++){
            if(num[i]==0){
                break;
            }
        }
        return i;
    }
    int judgeTree(int A,int B){
        if(A==-1&&B==-1){
            return 1;
        } 
        if((A==-1&&B!=-1)||(A!=-1&&B==-1)){
            return 0;
        }
        if(treeA[A].data!=treeB[B].data){
            return 0;
        }
        
        if(treeA[A].l==-1&&treeB[B].l==-1){
            return judgeTree(treeA[A].r,treeB[B].r);
        }
        if(treeA[A].l!=-1&&treeB[B].l!=-1&&treeA[treeA[A].l].data==treeB[treeB[B].l].data){
            return judgeTree(treeA[A].l,treeB[B].l) &&judgeTree(treeA[A].r,treeB[B].r);
        }else{
            return judgeTree(treeA[A].l,treeB[B].r) &&judgeTree(treeA[A].r,treeB[B].l);
        }
        
    }
    int main()
    {
        char a;
        int rootA=-1,rootB=-1;
        int n;
        scanf("%d",&n);
        rootA=initTree(n,treeA);
        scanf("%d",&n);
        rootB=initTree(n,treeB);
        if(n==1){
            if(treeA[0].data!=treeB[0].data){
                printf("No");
            }else{
                printf("Yes");
            }
            return 0;
        }
        if(n==0){
            printf("Yes");
            return 0;
        }
        if(judgeTree(rootA,rootB)){
            printf("Yes");
        }else{
            printf("No");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    解题思路

    这题写的优点绕了,主要是给你了树的结点,要构建树就得先找到根节点,根节点也就是没有被指向过的结点,只要用一个数组记录被指向的节点编号,然后找出没有被指的就行。这里绕的就是判断两棵树是否是同构的问题,无非就是分成以下几种情况

    1. 两棵树当前结点都为NULL,那肯定这两结点是符合的
    2. 两棵树当前结点一个为NULL,一个不为NULL,这肯定是不符合同构的原则
    3. 两棵树当前节点都不为NULL但值不相等,这也不符合同构的原则
    4. 两棵树当前结点不为NULL,且一边的子树值相等,那就对应子树找下去就行
    5. 最后是其他的情况,就是一遍的子树不相等,那么交叉找,这就可能是已经交换的情况

    差不多就这些,思路就这样。

  • 相关阅读:
    OpenCV oom问题解决
    【如何看待Unity收费】对标中小公司的待就业者的该如何做
    记录获取蓝鲸智云token的过程
    ClickHouse 视图(View)
    【mysql】关于mysql的数据结构特点 索引特点
    c++文件的打开、读写和关闭。缓冲区的使用和控制。
    c++视觉图像线性混合
    重新认知发明,全网保姆级入门说明
    Linux中用嵌套方式打印
    24.缓存
  • 原文地址:https://blog.csdn.net/weixin_44546342/article/details/126082601