PTA練習題---樹的同構
阿新 • • 發佈:2019-02-03
問題描述:
給定兩棵樹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
題目思路講解:https://www.bilibili.com/video/av14272542/index_2.html#page=2
需要解決的問題:
1.二叉樹用什麼形式表示,本題用了靜態連結串列的形式表示二叉樹。
2.怎麼建立二叉樹
3.如何判別兩個二叉樹是否同構
具體程式碼如下:
#include <stdio.h> #define MaxTree 10 #define ElementType char #define Tree int #define Null -1 struct TreeNode { ElementType Element; Tree Left; Tree Right; }T1[MaxTree],T2[MaxTree]; //T1和T2陣列的每一個元素的型別都是struct TreeNode型別 //T1和T2是全域性變數 Tree BuildTree(struct TreeNode T[]) { int i,N,check[MaxTree]; Tree Root=Null; char cl,cr; scanf("%d\n",&N); if(N) { for(i=0;i<N;i++) //check陣列用來判斷根的位置 check[i]=0; //每個結點初始對應的 check[i]初始化為0 for(i=0;i<N;i++) { scanf("%c %c %c\n",&T[i].Element,&cl,&cr); if(cl!='-') //這個if。。else語句用來設定當前結點的左兒子是否存在 { T[i].Left=cl-'0'; check[T[i].Left]=1; //如果左兒子存在,則左兒子位置處的check值設定為1 } else T[i].Left=Null; if(cr!='-') { T[i].Right=cr-'0'; check[T[i].Right]=1; } else T[i].Right=Null; } for(i=0;i<N;i++) { if(!check[i]) //如果check[i]為0,則找到了這個位置i為根,立馬跳出迴圈 { Root=i; //T[i]中某一個結點,如果沒有任何其他結點的 Left和Right指向它,則該結點是根 break; } } } return Root; } int Isomorphic(Tree R1,Tree R2) //從根開始比較每個結點的兩個兒子是否相等。必然會用到遞迴 { if((R1==Null)&&(R2==Null)) //如果兩個樹的根均為空 ,基準情形 return 1; if(((R1==Null)&&(R2!=Null))||((R1!=Null)&&(R2==Null))) //如果兩個樹的僅其中 一個根為空 return 0; if(T1[R1].Element!=T2[R2].Element) //如果兩個樹的根的元素不同 return 0; if((T1[R1].Left==Null)&&(T2[R2].Left==Null)) //如果根結點左子樹是空的,則從右子樹開始判斷 return Isomorphic(T1[R1].Right,T2[R2].Right); if((T1[R1].Left!=Null)&&(T2[R2].Left!=Null)&&((T1[T1[R1].Left].Element)==(T2[T2[R2].Left].Element))) //左邊同時是不空的,且左兒子元素也是一樣的 return(Isomorphic(T1[R1].Left,T2[R2].Left)&&Isomorphic(T1[R1].Right,T2[R2].Right)); //則通過遞迴判斷左兒子和右兒子 是否相同 else //兩個樹的左子樹都不空,但是左兒子不想等, 交換左右兒子進行判斷 return(Isomorphic(T1[R1].Left,T2[R2].Right)&&Isomorphic(T1[R1].Right,T2[R2].Left)); } //程式結構:輸入並建立兩個二叉樹,然後判斷是否同構 //建立兩個函式:讀取資料建立二叉樹的函式,二叉樹同構判別函式 int main() { Tree R1,R2; //樹的根 R1=BuildTree(T1); //T1是結構陣列,是全域性變數 R2=BuildTree(T2); if(Isomorphic(R1,R2)) //判別是否同構並輸出 printf("Yes\n"); else printf("No\n"); return 0; }