7-10 樹的同構(25 point(s))
阿新 • • 發佈:2019-01-28
給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。例如圖1給出的兩棵樹就是同構的,因為我們把其中一棵樹的結點A、B、G的左右孩子互換後,就得到另外一棵樹。而圖2就不是同構的。
圖1
圖2
輸入格式:
輸入給出2棵二叉樹樹的資訊。對於每棵樹,首先在一行中給出一個非負整數N (≤10),即該樹的結點數(此時假設結點從0到N−1編號);隨後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
code:
#include <stdio.h> #include <string.h> struct TNode{ char Data;//字母 int Left,Right;//左右兒子編號 };//建立樹的結構體 typedef struct TNode Tree;//typedef簡化名稱 Tree t1[12],t2[12];//兩棵樹的陣列用於比較 int Read(Tree t[]){ int i; int n;//節點個數 int pre[12];//祖先陣列,用於判斷樹根 int root = -1;//樹根標號,初始化為-1 memset(pre,0,sizeof(pre)) ; scanf("%d",&n); if(n){//如果n不為零執行 for(i = 0; i < n; i++){ char l,r;//記錄左右兒子的值 scanf(" %c %c %c",&t[i].Data,&l,&r); if(l!='-'){ t[i].Left = l-'0';//如果是數字,左子樹記錄該數字 pre[t[i].Left] = 1;//表示這個左孩子編號有父親 } else{ t[i].Left = -1; } if(r!='-'){//右邊同理 t[i].Right = r-'0'; pre[t[i].Right] = 1; } else{ t[i].Right = -1; } } }//記錄完畢 //找根 for(i = 0; i < n; i++){ if(!pre[i]){//如果有節點父親是0,說明沒父親為樹根 root = i; break; } } return root; } int isSame(int root1,int root2){ if((root1 == -1) && (root2 == -1)){//樹根都是空,同構返回1 return 1; } if(((root1 == -1) && (root2 != -1)) || ((root1 != -1) && (root2 == -1))){//如果一個是空一個不空,不同構,返回0 return 0; } if((t1[root1].Data) != (t2[root2].Data)){//如果樹根值不同,不同構,返回0 return 0; } if((t1[root1].Left == -1) && (t2[root2].Left == -1)){//如果左子樹都是空的,判斷右子樹 return isSame(t1[root1].Right,t2[root2].Right); } if((t1[root1].Left != -1) && (t2[root2].Left != -1) && (t1[t1[root1].Left].Data == t2[t2[root2].Left].Data)){//如果左樹不空且左子樹值想同,判斷其左右子樹 return (isSame(t1[root1].Left,t2[root2].Left) && isSame(t1[root1].Right,t2[root2].Right)); } else{//如果左子樹有一個空的,或者兩個樹不空 左子樹的值不同 ,交換左右子樹判斷 return (isSame(t1[root1].Left,t2[root2].Right) && isSame(t1[root1].Right,t2[root2].Left)); } } int main(){ int root1,root2;//樹根節點編號 root1 = Read(t1);//讀取 root2 = Read(t2); if(isSame(root1,root2))//判斷是否同構 printf("Yes\n"); else printf("No\n"); return 0; }