• 树的同构


    一:题目
    7-3 树的同构 (25 分)
     

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


    图1

    图2

    现给定两棵树,请你判断它们是否是同构的。

    输入格式:

    输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤),即该树的结点数(此时假设结点从0到N1编号);随后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
    二:具体实现
    #include<iostream>
    #include<cstdlib>
    using namespace std;
    typedef struct tree
    {
        char c;
        char c1[2];
        int d[2];
        tree *lchild,*rchild,*parent;
    }*node;
    node* Read(int &n)
    {
        node *p;
        cin>>n;
        p=new node[n];         //一定要给指针开辟空间
        for(int i=0;i<n;i++)
        {
            p[i]=new tree;
            p[i]->lchild=p[i]->rchild=NULL;
        }
        for(int i=0;i<n;i++)
        {
            cin>>p[i]->c;
            cin>>p[i]->c1[0]>>p[i]->c1[1];
            if(p[i]->c1[0]=='-')
                p[i]->d[0]=-1;
            else
                p[i]->d[0]=(int)p[i]->c1[0]-48;
            if(p[i]->c1[1]=='-')
                p[i]->d[1]=-1;
            else
                p[i]->d[1]=(int)p[i]->c1[1]-48;
        }
        return p;
    }
    tree* Creatree(node *p,int n)
    {
        for(int i=0;i<n;i++)
        {
            if(p[i]->d[0]!=-1)
            {
                p[i]->lchild=p[p[i]->d[0]];
                p[p[i]->d[0]]->parent=p[i];
            }
    
            else
                p[i]->lchild=NULL;
            if(p[i]->d[1]!=-1)
            {
                p[i]->rchild=p[p[i]->d[1]];
                p[p[i]->d[1]]->parent=p[i];
            }
            else
                p[i]->rchild=NULL;
        }
        for(int i=0;i<n;i++)
        {
            if(p[i]->parent==NULL)
                return p[i];
        }
    }
    void Compare(tree *p,tree *p1)
    {
        if(p==NULL&&p1==NULL)//laing
        {
            cout<<"Yes";exit(0);
        }
        else if((p==NULL&&p1!=NULL)||(p!=NULL&&p1==NULL))
        {
            cout<<"No";exit(0);
        }
        else
        {
                if(p->c!=p1->c)
                {
                    cout<<"No";exit(0);
                }
                else
                {
                    if(p->lchild!=NULL&&p->rchild!=NULL&&p1->lchild!=NULL&&p1->rchild!=NULL)//两者左右孩子都不为空
                    {
                        if((p->lchild->c==p1->lchild->c&&p->rchild->c==p1->rchild->c)||(p->lchild->c==p1->rchild->c&&p->rchild->c==p1->lchild->c))
                        {
                            if(p->lchild->c==p1->lchild->c&&p->rchild->c==p1->rchild->c)
                            {Compare(p->lchild,p1->lchild);Compare(p->rchild,p1->rchild);}
                            else if(p->lchild->c==p1->rchild->c&&p->rchild->c==p1->lchild->c)
                            {Compare(p->lchild,p1->rchild);Compare(p->rchild,p1->lchild);}
                        }
                        else
                        {
                        cout<<"No";
                        exit(0);
                        }
                    }
                    else if(p->lchild!=NULL&&p->rchild==NULL&&p->lchild!=NULL&&p->rchild==NULL)//两者左孩子都不空,右孩子都空
                    {
                        if(p->lchild->c!=p1->lchild->c)
                        {
                            cout<<"No";
                            exit(0);
                        }
                        else
                        Compare(p->lchild,p1->lchild);
                    }
                    else if(p->lchild==NULL&&p->rchild!=NULL&&p->lchild==NULL&&p->rchild!=NULL)//两者右孩子都不空,左孩子都空
                    {
                        if(p->rchild->c!=p1->rchild->c)
                        {
                            cout<<"No";
                            exit(0);
                        }
                        else
                        Compare(p->rchild,p1->rchild);
                    }
                    else if(p->lchild!=NULL&&p->rchild==NULL&&p->lchild==NULL&&p->rchild!=NULL)//前者左孩子不空,后者右孩子不空
                    {
                        if(p->lchild->c!=p1->rchild->c)
                        {
                            cout<<"No";
                            exit(0);
                        }
                        else
                        Compare(p->lchild,p1->rchild);
                    }
                    else if(p->lchild==NULL&&p->rchild!=NULL&&p->lchild!=NULL&&p->rchild==NULL)//前者右孩子不空,后者左孩子不空
                    {
                        if(p->rchild->c!=p1->lchild->c)
                        {
                            cout<<"No";
                            exit(0);
                        }
                        else
                        Compare(p->rchild,p1->lchild);
                    }
                    else if(p->lchild==NULL&&p->rchild==NULL&&p->lchild==NULL&&p->rchild==NULL)//两者都没有孩子
                    {}
                    else
                    {
                        cout<<"No";
                        exit(0);
                    }
    
                }
        }
        cout<<"Yes";
        exit(0);
    }
    int main()
    {
        node *p,*p1;
        tree *q,*q1;
    /* 声明指针不会创建用于存储的内存空间。
     指针声明时,指向的位置不确定,程序运行时,如果你运气好可能不出错,但是下次动态分配内存的时候你可能就没这么幸运了。
    例子
    int *a;
    *a=12;
    这是一个典型的错误:因为在分配内存时你无法确定 a 指向的位置,所以你下次 *a或者访问a时,
    可能带来:Program received signal SIGSEGV, Segmentation fault.*/
        q=new tree;
        q1=new tree;
        p=new node;
        p1=new node;
        int n=0;
        p=Read(n);
        q=Creatree(p,n);
        p1=Read(n);
        q1=Creatree(p1,n);
        Compare(q,q1);
    }

    三:总结

    1.定义二级指针后,一定不要忘了给二级指针初始化!

    2.定义指针后一定要给其开辟空间,不然很可能会出错。如:

    1.声明指针不会创建用于存储的内存空间。
    2.指针声明时,指向的位置不确定,程序运行时,如果你运气好可能不出错,但是下次动态分配内存的时候你可能就没这么幸运了。
    例子:
    int *a;
    *a=12
    这是一个典型的错误:因为在分配内存时你无法确定 a 指向的位置,所以你下次 *a或者访问a时,
    可能带来:Program received signal SIGSEGV, Segmentation fault.(调试出现的错误)





  • 相关阅读:
    几个影响sql性能语句的例子
    orderby工作原理 + 最小代价取随机数
    count(*)实现原理+两阶段提交总结
    脏页flush和收缩表空间
    mysql本身用错索引+给字符串字段加索引
    Java概念辨析:equals和== equals和hashCode
    abstract方法必须在abstract类中 这句话是对的还是错的?
    java实际项目中interface和abstract interface 区别
    【timeisprecious】【JavaScript 】JavaScript String 对象
    Linux学习(三)putty,xshell使用以及密匙登陆
  • 原文地址:https://www.cnblogs.com/zwsmile/p/11558973.html
Copyright © 2020-2023  润新知