7-3 树的同构 (25分)
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
现给定两棵树,请你判断它们是否是同构的。
输入格式:
输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。
输出格式:
如果两棵树是同构的,输出“Yes”,否则输出“No”。
解题思路:
先创建全局变量设置flag标志位,初始值为true
注:节点为空用0表示,不为空用1表示
1.查找根节点
没有其他节点指向的节点
2.创建二叉树(如果节点个数为0,就不创建)
3.比较叉树
(1)两个根节点分三种情况
00:不改变flag
10、01:改变flag为false
11:判断以此节点做根节点的树是否同构
(2)若根值相同,判断孩子节点
两棵树的孩子节点的状态数有:0000、1111、1010、1001、0101、0110和其他,其他状态时必不为同构,0000不改变flag的值,1111、1010、1001、0101、0110找相同的节点值,找不到就改变flag为false,找到就递归判断。
#include<iostream>
#include <limits.h>
#include<vector>
using std::cout;
using std::cin;
using std::endl;
typedef unsigned int uint;
typedef class node* Tree;
constexpr int maxsize = 15;
class node {
public:
char val;
node* lchild;
node* rchild;
node(char val) :val{ val }, lchild{ NULL }, rchild{NULL} {}
};
Tree creat(char a[maxsize][4],int pos) {
Tree T{NULL};
T = new node(a[pos][0]);
if (a[pos][1] != '-') {
T->lchild = creat(a, a[pos][1]-'0');
}
if (a[pos][2] != '-') {
T->rchild = creat(a, a[pos][2] - '0');
}
return T;
}
int get_pos(char a[maxsize][4],int n) {
for (int i = 0; i < n; i++) {
if (a[i][1] != '-')
a[a[i][1] - '0'][3] = 0;
if (a[i][2] != '-')
a[a[i][2] - '0'][3] = 0;
}
for (int i = 0; i < n; i++) {
if (a[i][3] == 1)
return i;
}
}
void pre_show(Tree T) {
if (T == NULL) return;
cout << T->val;
pre_show(T->lchild);
pre_show(T->rchild);
}
bool flag=true;
void compare(Tree T1, Tree T2) {
if (T1 == NULL && T2 == NULL)
;
else if (T1 == NULL && T2 != NULL) {
flag = false;
}
else if (T2 == NULL && T1 != NULL) {
flag = false;
}
else {
if (T1->val == T2->val) {
if (!T1->lchild && !T1->rchild && !T2->lchild && !T2->rchild)
;
else if (T1->lchild && T1->rchild && T2->lchild && T2->rchild) {
if (T1->lchild->val == T2->lchild->val) {
if (T1->rchild->val == T2->rchild->val) {
compare(T1->lchild, T2->lchild);
compare(T1->rchild, T2->rchild);
}
else flag = false;
}
else if (T1->lchild->val == T2->rchild->val) {
if (T1->rchild->val == T2->lchild->val) {
compare(T1->lchild, T2->rchild);
compare(T1->rchild, T2->lchild);
}
else flag = false;
}
else flag = false;
}
else if (!T1->lchild && T1->rchild && T2->lchild && !T2->rchild) {//0110
if (T1->rchild->val == T2->lchild->val) {
compare(T1->rchild, T2->lchild);
}
else flag = false;
}
else if (T1->lchild && !T1->rchild && !T2->lchild && T2->rchild) {//1001
if (T1->lchild->val == T2->rchild->val) {
compare(T1->lchild, T2->rchild);
}
else flag = false;
}
else if (!T1->lchild && T1->rchild && !T2->lchild && T2->rchild) {//0101
if (T1->rchild->val == T2->rchild->val) {
compare(T1->rchild, T2->rchild);
}
else flag = false;
}
else if (T1->lchild && !T1->rchild && T2->lchild && !T2->rchild) {//1010
if (T1->lchild->val == T2->lchild->val) {
compare(T1->lchild, T2->lchild);
}
else flag = false;
}
else flag = false;
}
else flag = false;
}
}
int main() {
int n, m,pos;//pos是根节点的位置
char a[maxsize][4]{};
char b[maxsize][4]{};
Tree T1{ NULL }, T2{ NULL };
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i][0] >> a[i][1] >> a[i][2];
a[i][3] = 1;
}
pos = get_pos(a,n);
if(n!=0)
T1 = creat(a, pos);
//pre_show(T1);
cin >> m;
for (int i = 0; i < n; i++) {
cin >> b[i][0] >> b[i][1] >> b[i][2];
b[i][3] = 1;
}
pos = get_pos(b,m);
if(m!=0)
T2 = creat(b, pos);
//pre_show(T2);
if (n != m) cout <<"No";
else {
compare(T1, T2);
if (flag)
cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}