同构树

什么是同构树:

给定两颗树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);//层次遍历 
    */
}
View Code

 快读版输入:

#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);//层次遍历 
}
View Code

 

posted @ 2020-04-02 21:33  sumoier  阅读(720)  评论(0编辑  收藏  举报