1. 程式人生 > >03-樹1 樹的同構 (25分)

03-樹1 樹的同構 (25分)

給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。例如圖1給出的兩棵樹就是同構的,因為我們把其中一棵樹的結點A、B、G的左右孩子互換後,就得到另外一棵樹。而圖2就不是同構的。


圖1


圖2

現給定兩棵樹,請你判斷它們是否是同構的。

輸入格式:

輸入給出2棵二叉樹樹的資訊。對於每棵樹,首先在一行中給出一個非負整數NN (1010),即該樹的結點數(此時假設結點從0到N1N1編號);隨後NN行,第ii行對應編號第ii個結點,給出該結點中儲存的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
主要思路:
1、合理建樹並尋找根結點
2、遞迴時的樹的同構與不同構的多種情形的考慮(見程式碼註釋)
不足之處:
1、遞迴時直接在vector上判斷孩子結點的情況導致程式碼可讀性變差
#include <iostream>
#include <vector>

using namespace std;

#define Max_Node 11
#define END -1

typedef struct node
{
    char value;
    int left;
    int right;
}Node;

void CreateTree(vector<Node>& Tree,int N)//獲取樹的輸入,並將輸入的字符合理轉化成整型數字
{
    
    char value,left,right;
    for (int i=0; i<N; ++i)
    {
        cin>>value>>left>>right;
        Tree[i].value=value;
        
        if (left=='-')
        {
            Tree[i].left=END;
        }else
        {
            Tree[i].left=left-'0';
        }
        
        if (right=='-')
        {
            Tree[i].right=END;
        }else
        {
            Tree[i].right=right-'0';
        }
    }
}

int FindTreeRoot(vector<Node>& Tree,int N)//尋找樹的樹根(樹根沒有其它的結點指向它)
{
    int Flag[Max_Node];
    for (int i=0; i<N; ++i)
    {
        Flag[i]=0;
    }
    
    for (int i=0; i<N; ++i)
    {
        if (Tree[i].left!=END)
        {
            Flag[Tree[i].left]=1;
        }
        if (Tree[i].right!=END)
        {
            Flag[Tree[i].right]=1;
        }
    }
    
    int k;
    for (k=0; k<N; ++k)
    {
        if (Flag[k]==0)
        {
            break;
        }
    }
    return k;
}

bool IsOmorphic(int Root1,int Root2,vector<Node>& Tree1,vector<Node>& Tree2)//遞迴判斷兩樹是否同構
{
    if (Tree1[Root1].value==Tree2[Root2].value)
    {
        //兩結點相等,並都是葉子結點
        if (Tree1[Root1].left==END && Tree1[Root1].right==END && Tree2[Root2].left==END && Tree2[Root2].right==END)
        {
            return true;
        }
        
        //以下四種情況都是,兩個結點都是有一個孩子為空,另一個子樹不空且這兩個孩子相等的情形
        if (Tree1[Tree1[Root1].left].value==Tree2[Tree2[Root2].left].value && Tree1[Root1].right==END && Tree2[Root2].right==END)
        {
            return IsOmorphic(Tree1[Root1].left, Tree2[Root2].left, Tree1, Tree2);
        }
        if (Tree1[Tree1[Root1].left].value==Tree2[Tree2[Root2].right].value && Tree1[Root1].right==END && Tree2[Root2].left==END)
        {
            return IsOmorphic(Tree1[Root1].left, Tree2[Root2].right, Tree1, Tree2);
        }
        if (Tree1[Tree1[Root1].right].value==Tree2[Tree2[Root2].left].value && Tree1[Root1].left==END && Tree2[Root2].right==END)
        {
            return IsOmorphic(Tree1[Root1].right, Tree2[Root2].left, Tree1, Tree2);
        }
        if (Tree1[Tree1[Root1].right].value==Tree2[Tree2[Root2].right].value && Tree1[Root1].left==END && Tree2[Root2].left==END)
        {
            return IsOmorphic(Tree1[Root1].right, Tree2[Root2].right, Tree1, Tree2);
        }
        
        //以下兩種情形,兩個結點的孩子都相等
        if (Tree1[Tree1[Root1].left].value==Tree2[Tree2[Root2].left].value && Tree1[Tree1[Root1].right].value==Tree2[Tree2[Root2].right].value)
        {
            return (IsOmorphic(Tree1[Root1].left, Tree2[Root2].left, Tree1, Tree2))&&(IsOmorphic(Tree1[Root1].right, Tree2[Root2].right, Tree1, Tree2));
        }
        if (Tree1[Tree1[Root1].left].value==Tree2[Tree2[Root2].right].value && Tree1[Tree1[Root1].right].value==Tree2[Tree2[Root2].left].value)
        {
            return (IsOmorphic(Tree1[Root1].left, Tree2[Root2].right, Tree1, Tree2))&&(IsOmorphic(Tree1[Root1].right, Tree2[Root2].left, Tree1, Tree2));
        }
    }
    //不符合以上7種情況的其它情況都說明這兩棵樹不同構
    return false;
}

int main(int argc, const char * argv[])
{
    //Input
    int N1=0;
    cin>>N1;
    vector<Node> Tree1(Max_Node);
    CreateTree(Tree1,N1);
    int N2=0;
    cin>>N2;
    vector<Node> Tree2(Max_Node);
    CreateTree(Tree2,N2);
    
    
    if (N1!=N2)
    {
        cout<<"No";
    }else
    {
        if (N1==0)
        {
            cout<<"Yes";
        }else
        {
           
    
            //Build Tree
            int root1=FindTreeRoot(Tree1,N1);
            int root2=FindTreeRoot(Tree2,N2);
    
            //Judge
            if (IsOmorphic(root1, root2, Tree1, Tree2))
            {
                cout<<"Yes";
            }else
            {
                cout<<"No";
            }
        }
    
    }
    return 0;
}