同构树
什么是同构树:
给定两颗树T1和T2,如果T1可以通过若干次左右孩子交换变成T2,我们就称两棵树是同构的。
将整个过程拆分来看一下,增加一些二叉树的操作:
首先是二叉树的建立:
struct tnode{ char data; int right,left; }; void buildtree(tnode t[]) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>t[i].data>>t[i].left>>t[i].right; }
找二叉树的根节点:(就在刚才的代码中修改,其实很简单)
int buildtree(tnode t[]) { int n,root=-1,f[N]; memset(f,0,sizeof(f)); cin>>n; for(int i=1;i<=n;i++) { cin>>t[i].data>>t[i].left>>t[i].right; if(t[i].left>0) f[t[i].left]=1; if(t[i].right>0) f[t[i].right]=1; } for(int i=1;i<=n;i++) if(!f[i]) { root=i;break; } return root; }
对二叉树的遍历:
先序遍历:(其实在这个基础上稍微更改一下就可以实现中序和后序遍历)
void preord(int root,tnode t[]){ if(root!=-1){ cout<<root<<t[root].data<<" ";//这三个更改顺序就可以了 preord(t[root].left,t); preord(t[root].right,t); } }
层次遍历(利用队列):
void levelt(int root,tnode t[]){ queue<int> q; q.push(root); while(!q.empty()){ int r=q.front();q.pop();cout<<r<<t[r].data<<" "; if(t[r].left!=-1) q.push(t[r].left); if(t[r].right!=-1) q.push(t[r].right); } }
判断同构:
基本思路:1、如果两颗树均为空,认为同构;2、如果均不为空且值相等,则去递归判断左右子树是否相等或者T1左子树等于T2右子树&&T1右子树等于T2左子树;其余都为不同构
判断同构:
int issame(int r1,int r2){ if(r1==-1&&r2==-1) return 1; if((r1!=-1&&r2!=-1)&&(t1[r1].data==t2[r2].data)){ int one=issame(t1[r1].left,t2[r2].left)&&issame(t1[r1].right,t2[r2].right); int two=issame(t1[r1].left,t2[r2].right)&&issame(t1[r1].right,t2[r2].left); return (one||two); } else return 0; }
例题:
输入:
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 -
判断这两颗树是否为同构树,完整代码(稍微注意下输入):
#include <bits/stdc++.h> using namespace std; const int N=205; struct tnode{ char data; int right,left; }; tnode t1[N],t2[N]; int buildtree(tnode t[]){//建树 int n,root=-1,f[N]; char cl,cr; //cout<<f[0]<<endl; cin>>n; for(int i=0;i<n;i++) f[i]=-1; for(int i=0;i<n;i++){ cin>>t[i].data>>cl>>cr; if(cl=='-') t[i].left=-1; else{ int tmp=cl-'0'; f[tmp]=1;t[i].left=tmp; } if(cr=='-') t[i].right=-1; else{ int tmp=cr-'0'; f[tmp]=1;t[i].right=tmp; } } for(int i=0;i<n;i++) { if(f[i]==-1){ root=i;break; } } return root; } void preord(int root,tnode t[]){ if(root!=-1){ cout<<root<<t[root].data<<" "; preord(t[root].left,t); preord(t[root].right,t); } } void levelt(int root,tnode t[]){ queue<int> q; q.push(root); while(!q.empty()){ int r=q.front();q.pop();cout<<r<<t[r].data<<" "; if(t[r].left!=-1) q.push(t[r].left); if(t[r].right!=-1) q.push(t[r].right); } } int issame(int r1,int r2){ if(r1==-1&&r2==-1) return 1; if((r1!=-1&&r2!=-1)&&(t1[r1].data==t2[r2].data)){ int one=issame(t1[r1].left,t2[r2].left)&&issame(t1[r1].right,t2[r2].right); int two=issame(t1[r1].left,t2[r2].right)&&issame(t1[r1].right,t2[r2].left); return (one||two); } else return 0; } int main(){ int r1=buildtree(t1); int r2=buildtree(t2); if(issame(r1,r2)) cout<<"yes"; else cout<<"no"; /* preord(r1,t1);//前序遍历 cout<<endl; levelt(r1,t1);//层次遍历 */ }
快读版输入:
#include <bits/stdc++.h> using namespace std; const int N=205; struct tnode{ char data; int right,left; }; tnode t1[N],t2[N]; int read() { int x=0;char z=getchar(); while(!(z=='-'||z>='0'&&z<='9'))z=getchar(); if(z=='-') return -1; if(z=='-') return -1; while(z>='0'&&z<='9') x=(x<<3)+(x<<1)+z-'0',z=getchar(); return x; } int buildtree(tnode t[]){//建树 int n,root=-1,f[N]; char cl,cr; //cout<<f[0]<<endl; //cin>>n; n=read(); for(int i=0;i<n;i++) f[i]=-1; for(int i=0;i<n;i++){ //cin>>t[i].data>>cl>>cr; scanf("\n%c",&t[i].data); t[i].left=read(); if(t[i].left!=-1) f[t[i].left]=1; t[i].right=read(); if(t[i].right!=-1) f[t[i].right]=1; } /* if(cl=='-') t[i].left=-1; else{ int tmp=cl-'0'; f[tmp]=1;t[i].left=tmp; } if(cr=='-') t[i].right=-1; else{ int tmp=cr-'0'; f[tmp]=1;t[i].right=tmp; } } */ for(int i=0;i<n;i++) { if(f[i]==-1){ root=i;break; } } return root; } void preord(int root,tnode t[]){ if(root!=-1){ cout<<root<<t[root].data<<" "; preord(t[root].left,t); preord(t[root].right,t); } } void levelt(int root,tnode t[]){ queue<int> q; q.push(root); while(!q.empty()){ int r=q.front();q.pop();cout<<r<<t[r].data<<" "; if(t[r].left!=-1) q.push(t[r].left); if(t[r].right!=-1) q.push(t[r].right); } } int issame(int r1,int r2){ if(r1==-1&&r2==-1) return 1; if((r1!=-1&&r2!=-1)&&(t1[r1].data==t2[r2].data)){ int one=issame(t1[r1].left,t2[r2].left)&&issame(t1[r1].right,t2[r2].right); int two=issame(t1[r1].left,t2[r2].right)&&issame(t1[r1].right,t2[r2].left); return (one||two); } else return 0; } int main(){ int r1=buildtree(t1); int r2=buildtree(t2); if(issame(r1,r2)) cout<<"yes"; else cout<<"no"; //preord(r1,t1);//前序遍历 //cout<<endl; //levelt(r1,t1);//层次遍历 }