Emm,对于这道问题,我们有那些可以学习的呢?
首先是结构数组,其定义如下:
#define MaxTree 10
struct Node
{
char Element;
int Left;
int Right;
}T1[MaxTree], T2[MaxTree];
也就是数组中的没每一个元素都是一个结构体。即很方便的对数组元素进行检索,又能够包含多种类型的元素。
第二点值得我们学习的地方在于一种结构,在本题中,我们首先是定义了一个结构数组来存储输入元素,接下来呢?我们需要判断并找出第一个节点,也就是根节点。
我们如何去找呢?在标准答案中,是通过判断某一个元素是不是其他元素的孩子来决定的。
也即
Check[T1[R1].Left]这种形式来修改标志位,这种方法很棒的利用了数组的检索机制,很方便的就修改了某一个元素的根节点。
第三点我们要学习的就是他这个Isomorphic函数的迭代过程。很明显,对于树来说,这一个个过程都是重复的,我们只需要通过条件判断出一个的所有情形就能很方便的进行迭代下去。整体代码如下:
#include <stdio.h>
#define MaxTree 10
#define Null -1
struct Node
{
char Element;
int Left;
int Right;
}T1[MaxTree], T2[MaxTree];
//这里我们定义了两个结构数组,也就是数组的每一个元素都是一个结构体
int BuildTree(struct Node T[]);
int Isomorphic(int R1, int R2);
int main()
{
int R1, R2;
R1 = BuildTree(T1);//我们传入的是数组的地址,对数组进行了修改
R2 = BuildTree(T2);
if (Isomorphic(R1, R2)) printf("Yes");
else printf("No");
return 0;
}
int BuildTree(struct Node T[])
{
int num, i;
char cl, cr;
int Root = Null;
int Check[MaxTree] = { 0 };
scanf("%d\n", &num);
//将所有元素读入进来,读入进来容易,一个关键问题在于找到根节点,然后返回根节点,这样才能够对树进行检索
if (num)
{
for (i = 0; i < num; i++) Check[i] = 0;
for (i = 0; i < num; i++)
{
scanf(" %c %c %c", &T[i].Element, &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 (i = 0; i < num; i++)
if (!Check[i]) break;
Root = i;
}
return Root;
}
//我们检索一边,看一看某一个节点的孩还是不是他的孩不就行了嘛----不可以,答案方法很标准
int Isomorphic(int R1, int 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].Right, T2[R2].Left) &&
Isomorphic(T1[R1].Left, T2[R2].Right));
}
还要注意的是scanf("%c")是可以读入回车\n字符的,所以文中使用
scanf(" %c %c %c", &T[i].Element, &cl, &cr);
很巧妙的处理了前一行留下的空格。