pta树的同构

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值