树的同构

一:题目
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.(调试出现的错误)





原文地址:https://www.cnblogs.com/zwsmile/p/11558973.html