## Basic experiment 4-2.1 isomorphism of trees

given two trees T1 and T2. If T1 can be changed into T2 by several times of left and right child exchange, then we call two trees “isomorphic”. For example, the two trees shown in Figure 1 are isomorphic, because after we exchange the left and right children of nodes a, B and g of one tree, we get another tree. And Figure 2 is not isomorphic.

Figure 1 (isomorphism)Figure 2 (non isomorphic)

Basic experiment 4-2.1 isomorphism of trees (25 points)

## algorithm analysis

For the binary tree algorithm, I summed up two very important ideas in the process of doing the problem.

- The recursive definition of tree itself leads to degradation analysis and generalization verification.
- “Sentry” thought.

### Degradation analysis, generalization verification

since the tree itself is recursively defined, assuming that the algorithm required by the problem is true on the complex tree $t $, then every subtree of $t $must be true. More popular, for any tree that meets the conditions of the topic, it must be true, even if the tree can not be simplified any more.

the following uses this topic as an example to describe in detail how to analyze and verify.

#### analysis

First, we draw an extremely degenerate tree to study the isomorphism condition in the topic. As shown in the figure below, there are only two nodes in the tree.

Obviously, when the data domain of the node is not considered, the binary tree of two nodes has only two cases as shown in the figure above. There are only two cases of isomorphism.

**The first case**

for a binary tree on the left of a graph $t_ 1 $, it must be isomorphic with itself. Similarly, for the binary tree on the right of the graph $t_ 2 $, which is also isomorphic with oneself. According to the recursive property of binary tree, all its subtrees must be isomorphic with itself.

**The second situation**

in another case, we found that $t_ 1 $and $t_ Two dollars is also isomorphic. That’s $t_ Left subtree of $1 and $t_ The right subtree of $2 is isomorphic_ Right subtree of $1 (null) and $t_ The left subtree (null) of 2 $is isomorphic.

By analyzing the binary tree of two nodes, we find the condition of isomorphism. Namely:

- Two trees $t_ 1 $and $t_ 2 $the data fields of the current node are equal.
- $T_ Left subtree of $1 and $t_ Left subtree isomorphism of 2 $, $t_ 1 $right subtree and $t_ 2 $right subtree is isomorphic.
- $T_ Left subtree of $1 and $t_ The right subtree of $2 is isomorphic_ 1 $right subtree and $t_ 2 $left subtrees are isomorphic.

two trees are isomorphic as long as they satisfy the condition of $1 \ & \ & 2 $or $1 \ & \ & 3 $respectively.

**So. By simplifying the form of binary tree, we can intuitively and quickly analyze a row efficient algorithm (regardless of performance).**

#### Generalization verification

Then we can take our algorithm into a more complex binary tree for verification, and see if we can get a counterexample. Recently, we are busy reviewing the postgraduate entrance examination, and the time is limited. This step is for you to try.

## Sentinel thought

in the last step, I don’t know if you have noticed one small detail. In the second case, if a subtree is empty, we don’t judge it as empty. We only default that the empty subtree is isomorphic, that is, null is isomorphic to null.

this idea brings great convenience to our code implementation. We don’t need to judge whether it is a leaf node or not, and we don’t need to worry about whether a certain subtree needs special treatment when recursion occurs. Instead, we use a logical “sentry” to judge.

The concept of “sentry” is used in many classical algorithms. For example, quick sort, KMP algorithm and so on. Using sentinel flexibly is helpful to simplify the implementation of our recursive algorithm.

## Input processing

in addition, there is a small pitfall in this problem, that is, the input data is not given in the order of first, middle and last or in the order of hierarchical traversal. It should be given at random. We need to find the root node in the input data.

because it is a tree structure, we know that the tree is a semi-linear structure, each node has $1 $to $n $successors, but each node has only $1 $precursors at most. That is, except for the root node, the penetration of each node is $1 $. In other words, except for the root node, each node has a pointer or reference to it. So we can judge which is the root node by counting the in degree or the reference to the node. The only one that is not pointed to is the root node.

## code

```
#include <stdio.h>
typedef struct Node{
char c;
int lchild;
int rchild;
}BTNode;
int input_tree(int n, BTNode node[]);
/*
@Params node1 tree 1, node2 tree 2, I, subscript of current node of tree 1, and subscript of current node of J tree 2
@Return isomorphism returns 1, otherwise returns 0
*/
int is_same(BTNode node1[], BTNode node2[], int i, int j);
int main(){
BTNode node1[11]={0}, node2[11]={0};
int n;
scanf("%d", &n);
int root1 = input_ Tree (n, node1); // read the tree and return the subscript of the root of the tree
scanf("%d", &n);
int root2 = input_tree(n, node2);
int ans = is_ Same (node1, node2, root1, root2); // judge whether node1 and node2 are isomorphic
if(ans == 1) printf("Yes\n");
else printf("No\n");
return 0;
}
int input_tree(int n, BTNode node[]){
char ch, lc, rc;
int a[11]={0};
for(int i=0; i<n; i++){
scanf(" %c %c %c", &ch, &lc, &rc);
node[i].c = ch;
node[i].lchild = -1;
node[i].rchild = -1;
if (lc != '-'){
Node [i]. Lchild = LC - 48; // subtracting 48 from the ASCII code of a number is the value of the number
a[lc-48] = 1;
}
if (rc != '-'){
node[i].rchild = rc - 48;
a[rc-48] = 1;
}
}
int root = -1;
For (int i = 0; I < n; I + +) {// the subscript of the array 0 is the subscript of the root node
if(a[i]==0){
root = i;
break;
}
}
return root;
}
int is_same(BTNode node1[], BTNode node2[], int i, int j){
If ((I = = - 1 & & J! = - 1) | (I = = - 1 & & J! = - 1)) return 0; // one side is null and the other side is not null
If (I = = - 1 & & J = = - 1) return 1; // all current nodes are null
If (node1 [i]. C! = node2 [J]. C) return 0; // the characters are not equal
int ll = is_ Same (node1, node2, node1 [i]. Lchild, node2 [J]. Lchild); // left and left isomorphism
int rr = is_ Same (node1, node2, node1 [i]. Rchild, node2 [J]. Rchild); // right and right isomorphism
int lr = is_ Same (node1, node2, node1 [i]. Lchild, node2 [J]. Rchild); // left and right isomorphism
int rl = is_ Same (node1, node2, node1 [i]. Rchild, node2 [J]. Lcchild); // right and left isomorphism
If ((ll = = 1 & & RR = = 1) | (LR = = 1 & & RL = = 1)) return 1; // left left right isomorphism or left right left isomorphism, then the subtree is isomorphic
else return 0;
}
```