1. 程式人生 > >浙江大學資料結構mooc 03-樹1 樹的同構(25 分)

浙江大學資料結構mooc 03-樹1 樹的同構(25 分)

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

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


圖1


圖2

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

輸入格式:

輸入給出2棵二叉樹樹的資訊。對於每棵樹,首先在一行中給出一個非負整數N (10),即該樹的結點數(此時假設結點從0到N1編號);隨後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

思路解析: 主要分為三部分,樹的表示,建立二叉樹,同構判斷。

樹的表示,利用結構陣列的方式。看題,最大N不超過10,利用陣列不會浪費很大空間。陣列下標的儲存方式便於尋找。建樹,可以通過連結串列,也可以通過指標,這種資料輸入的方式,更適合陣列。

建立二叉樹,關鍵點在於,一次出入資料後,找到根節點是哪一個數。利用check陣列判斷,根節點即沒有其他數指向的點。

同構判斷,從根節點開始判斷,判斷根節點的資料以及左右字樹,注意利用遞迴的思想。

c++程式碼如下:

// TreeNodeIsomorphism.cpp : 定義控制檯應用程式的入口點。
//

 #include<iostream>

using namespace std;

#define ElementType char
#define Tree int
#define Null -1
#define MaxTree 10

struct TreeNode{

	ElementType Data;
	Tree Left;
	Tree Right;
};
Tree BuildTree(struct TreeNode T[]);
int Isomorphic(Tree R1, Tree R2);
struct TreeNode T1[MaxTree], T2[MaxTree];
int main()
{
	 Tree Root1 = BuildTree(T1);
	 Tree Root2 = BuildTree(T2);
	 int Re = Isomorphic(Root1, Root2);
	 if (Re == 1)
		 cout << "Yes";
	 else
		 cout << "No";
}


Tree BuildTree(struct TreeNode T[]) //建立二叉樹
{
	int N,Root;
	int check[MaxTree]; //判斷根節點
	char cl, cr;
	cin >> N;
	if (N == 0)
		return Null;
	for (int i = 0; i < N; i++) check[i] = 0;
	for (int i = 0; i < N; i++)
	{
		cin >> T[i].Data >> cl >> cr;
		if (cl != '-')
		{
			T[i].Left = cl - '0';
			check[T[i].Left] = 1;
		}
		else T[i].Left = Null;
		if (cr != '-')
		{
			T[i].Right = cr - '0';
			check[T[i].Right] = 1;
		}
		else T[i].Right = Null;
	}
	for (int i = 0; i < N; i++)
	{
		Root = i;
		if (check[i] == 0) break;
		
	}
	return Root;
}

int Isomorphic(Tree R1, Tree R2) //同構判斷
{
	if (R1 == Null&&R2 == Null)
		return 1; /*both roots empty*/
	if (((R1 == Null) && (R2 != Null)) || (R1 != Null&&R2 == Null))
		return 0;/*roots are diffent,one of is empty*/
	if (T1[R1].Data != T2[R2].Data)
		return 0;/*roots are different*/
	if (T1[R1].Left == Null && T2[R2].Left == Null)
		return Isomorphic(T1[R1].Right, T2[R2].Right);
	if(T1[R1].Right==Null&& T2[R2].Right == Null)
		return Isomorphic(T1[R1].Left, T2[R2].Left);
	if (((T1[R1].Left != Null) && (T2[R2].Left != Null)) && ((T1[T1[R1].Left].Data) == (T2[T2[R2].Left].Data)))
		return (Isomorphic(T1[R1].Right, T2[R2].Right) && Isomorphic(T1[R1].Left,T2[R2].Left));
	else
		return (Isomorphic(T1[R1].Right, T2[R2].Left) && Isomorphic(T1[R1].Left, T2[R2].Right));

}