数据结构实验之二叉树一:树的同构
Time Limit: 1000MS Memory limit: 65536K
题目描述
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
图1
图2
现给定两棵树,请你判断它们是否是同构的。
输入
输入数据包含多组,每组数据给出
2
棵二叉树的信息。对于每棵树,首先在一行中给出一个非负整数
N (
≤
10)
,即该树的结点数(此时假设结点从
0
到
N−1
编号);随后
N
行,第
i
行对应编号第
i
个结点,给出该结点中存储的
1
个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出
”-”
。给出的数据间用一个空格分隔。
注意:题目保证每个结点中存储的字母是不同的。
注意:题目保证每个结点中存储的字母是不同的。
输出
如果两棵树是同构的,输出“
Yes
”,否则输出“
No
”。
示例输入
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 -
示例输出
Yes
#include <iostream> #include <algorithm> #include <cstring> using namespace std; typedef struct node { char data; struct node *lchild,*rchild; } node,*tree; struct nod { char data; //存节点值 int l,r; //存左子树和右子树非空的位置 } p[100]; int creat(tree &t,int n); int tongou(tree t1,tree t2); int sign[100],num; //标记此处有孩子 //void PreOrder(tree T); int main() { /*******第一棵树******/ char c,s,r; int a; while(cin>>a) { memset(sign,0,sizeof(sign)); for(int i=0; i<a; i++) { cin>>c>>s>>r; p[i].data=c; if(s=='-') p[i].l=-1; else { p[i].l=s-'0'; sign[p[i].l]=1; } if(r=='-') p[i].r=-1; else { p[i].r=r-'0';//字符转换为子树的位置 sign[p[i].r]=1; } } tree t1; if(a!=0) { int j; for( j=0; j<a; j++) { if(sign[j]!=1) break; } creat(t1,j); //cout<<j<<endl; } //PreOrder(t1);cout<<endl; /*****第二棵树****/ memset(sign,0,sizeof(sign)); cin>>a; for(int i=0; i<a; i++) { cin>>c>>s>>r; p[i].data=c; if(s=='-') p[i].l=-1; else { p[i].l=s-'0'; sign[p[i].l]=1; } if(r=='-') p[i].r=-1; else { p[i].r=r-'0';//字符转换为子树的位置 sign[p[i].r]=1; } } tree t2; int j; for( j=0; j<a; j++) if(sign[j]!=1) break;//找到编号位置没有值得地方,第一个缺0,第二个缺3//???? //cout<<j<<endl; creat(t2,j); //************************************ //PreOrder(t2);cout<<endl; /***判同构***/ num=0; tongou(t1,t2); if(num==a) cout<<"Yes\n"; else cout<<"No\n"; } } int creat(tree &t,int n) { t=(tree)malloc(sizeof(node)); t->lchild=NULL; t->rchild=NULL;//必须初始化,这是树的终止,比如 如果没有,遍历输出会无限循环 if(!t) exit(0); t->data=p[n].data; //cout<<t->data<<endl; if(p[n].l!=-1) creat(t->lchild,p[n].l); if(p[n].r!=-1) creat(t->rchild,p[n].r); } int tongou(tree t1,tree t2) { if(!t1&&!t2) return 1; //2空树一定同构 else if(t1&&t2) //再同构需要2树都不为空 { if(t1->data!=t2->data) //2节点不同一定不同构 return 0; else num++; //需要每一个都相等 if(tongou(t1->lchild,t2->lchild)&&tongou(t1->rchild,t2->rchild) ||tongou(t1->lchild,t2->rchild)&&tongou(t1->rchild,t2->lchild)) //左子树等于左子树或左子树等于右子树,右子树等于左子树即同构 return 1; else return 0; } else return 0; } /*void PreOrder(tree T) { if(T != NULL) { cout<<T->data; PreOrder(T->lchild); PreOrder(T->rchild); } }测试用的函数*/