判断一棵二叉树是否对称

目录

解题思路

宏定义

二叉树定义

实现函数

测试代码

测试结果


题目描述

设计一个算法,判断一棵二叉树是否对称。 

来源:2022东北大学软件工程858考研真题第2题 

解题思路

方法一(巧妙)

采用层次遍历,先将根节点的左孩子和右孩子入队,用L和R记录出队元素,对比L、R,若值不同,返回0,否则将下一层结点入队,每次入队按照以下顺序:

                L的左孩子->R的右孩子->L的右孩子->R的左孩子

这样的入队顺序可以保证L和R出队时保持以根节点为对称轴的相对位置。

方法二(容易想到)

一个很朴素的方法,将二叉树镜像得到一颗新树,再和原二叉树进行比较。可将问题转化为判断两棵二叉树是否完全相同。只是要注意,二叉树镜像之后改变了原树,需要再镜像之前复制一棵树。

将二叉树镜像的算法,其实就是将每个结点的左右子树交换位置。

                http://t.csdnimg.cn/nPvkUicon-default.png?t=N7T8http://t.csdnimg.cn/nPvkU

下面是判断两棵二叉树是否完全相同,使用递归的方法:

                T1、T2为传入的两个子树;

                若T1、T2都为空,返回1;

                若一个空、一个不空,返回0;

                若都不空,递归对比T1、T2的左子树和T1、T2的右子树;

宏定义

#define TElemType char

二叉树定义

typedef struct TreeNode{ 
    TElemType val;         
    struct TreeNode*left;
    struct TreeNode*right;
}*Tree,TreeNode;

[注] 上述宏定义和结构体定义是答题时要写的答案,并不是代码实现时的定义,代码实现稍有不同,感兴趣可去“help.h”中查看。

实现函数

  • 方法一
int DBDX_2022_2_1(Tree T){
	if(!T) return 1;							//空树认为是对称的了
	SqQueue Q;									//定义队列 
	InitSqQueue(&Q);							//初始化队列 
	EnSqQueue(&Q,T->left);						//根左孩子入队 
	EnSqQueue(&Q,T->right);						//根右孩子入队 
	while(!SqQEmpty(Q)){
		TreeNode*L=DeSqQueue(&Q);				//每次先出队的入队时都是根节点左子树的孩子 
		TreeNode*R=DeSqQueue(&Q);				//每次先出队的入队时都是根节点右子树的孩子 
		if(!L&&!R)	continue;					//L,R都为空 
		if(!L||!R)  return 0;					//上一步已经判断两个都为空的情况,所以这个条件语句执行时一定是一个空,一个不空 
		else{									//只剩一种情况:两个都不为空 
			if(R->val==L->val){					//值相等,继续往下判断 
				EnSqQueue(&Q,L->left);			//每次入队顺序  左左 右右 左右 右左 
				EnSqQueue(&Q,R->right);
				EnSqQueue(&Q,L->right);
				EnSqQueue(&Q,R->left);
			}else return 0;						//不等时,返回0 
		}
	}
	return 1;									//全都遍历结束,就是每个结点以跟为对称轴,对面都有一个一样的结点 
}
  • 方法二
Tree CopyTree(Tree T){							//复制一颗二叉树 
	Tree T_=(Tree)malloc(sizeof(TreeNode));
	T_->ltag=T_->rtag=-1;   					//不用管,不用做线索二叉树时赋值为-1 
	if(T){
		T_->val=T->val;
		T_->left=CopyTree(T->left);
		T_->right=CopyTree(T->right);
		return T_;
	}
	return NULL;
}
void TreeSwap(Tree T){							//交换二叉树每个结点的左右子树 
    if(!T) return;
    TreeNode*temp=T->left;
    T->left=T->right;
    T->right=temp;
    TreeSwap(T->left);
    TreeSwap(T->right);
}
int isSame(Tree T1,Tree T2){					//判断两颗二叉树是否相同 
	if(!T1&&!T2) return 1;						//T1、T2都为空 
	else if(!T1||!T2) return 0;					//一个空、一个不空 
	else{										//都不空 
		if(T1->val!=T2->val) return 0;			//结点值不相等 
		else return isSame(T1->left,T2->left) && isSame(T1->right,T2->right);    //判断左右子树是否完全相同 
	}
}
int DBDX_2022_2_2(Tree T){
	if(!T) return 1;
	Tree T_=CopyTree(T);
	TreeSwap(T_);
	return isSame(T,T_);
}

测试代码

#include"../help.h"
/*
题目:设计一个算法,判断一棵二叉树是否对称。 
出自:2022东北大学软件工程858考研真题第2题 
*/
//方法一 
int DBDX_2022_2_1(Tree T){
	if(!T) return 1;							//空树认为是对称的了
	SqQueue Q;									//定义队列 
	InitSqQueue(&Q);							//初始化队列 
	EnSqQueue(&Q,T->left);						//根左孩子入队 
	EnSqQueue(&Q,T->right);						//根右孩子入队 
	while(!SqQEmpty(Q)){
		TreeNode*L=DeSqQueue(&Q);				//每次先出队的入队时都是根节点左子树的孩子 
		TreeNode*R=DeSqQueue(&Q);				//每次先出队的入队时都是根节点右子树的孩子 
		if(!L&&!R)	continue;					//L,R都为空 
		if(!L||!R)  return 0;					//上一步已经判断两个都为空的情况,所以这个条件语句执行时一定是一个空,一个不空 
		else{									//只剩一种情况:两个都不为空 
			if(R->val==L->val){					//值相等,继续往下判断 
				EnSqQueue(&Q,L->left);			//每次入队顺序  左左 右右 左右 右左 
				EnSqQueue(&Q,R->right);
				EnSqQueue(&Q,L->right);
				EnSqQueue(&Q,R->left);
			}else return 0;						//不等时,返回0 
		}
	}
	return 1;									//全都遍历结束,就是每个结点以跟为对称轴,对面都有一个一样的结点 
}
//方法二 
Tree CopyTree(Tree T){							//复制一颗二叉树 
	Tree T_=(Tree)malloc(sizeof(TreeNode));
	T_->ltag=T_->rtag=-1;   					//不用管,不用做线索二叉树时赋值为-1 
	if(T){
		T_->val=T->val;
		T_->left=CopyTree(T->left);
		T_->right=CopyTree(T->right);
		return T_;
	}
	return NULL;
}
void TreeSwap(Tree T){							//交换二叉树每个结点的左右子树 
    if(!T) return;
    TreeNode*temp=T->left;
    T->left=T->right;
    T->right=temp;
    TreeSwap(T->left);
    TreeSwap(T->right);
}
int isSame(Tree T1,Tree T2){					//判断两颗二叉树是否相同 
	if(!T1&&!T2) return 1;						//T1、T2都为空 
	else if(!T1||!T2) return 0;					//一个空、一个不空 
	else{										//都不空 
		if(T1->val!=T2->val) return 0;			//结点值不相等 
		else return isSame(T1->left,T2->left) && isSame(T1->right,T2->right);    //判断左右子树是否完全相同 
	}
}
int DBDX_2022_2_2(Tree T){
	if(!T) return 1;
	Tree T_=CopyTree(T);
	TreeSwap(T_);
	return isSame(T,T_);
}
int main(void) {
	   	char arr1[7]={'1','2','2','3','4','4','3'};
	   	Tree T1=Build_tree(arr1,7);
	   	print_arr_c(arr1,7);
	   	show_tree_target(T1,NULL,0);
	   	int res1=DBDX_2022_2_1(T1);			//方法一 
	   	printf("\nres1:%d\n",res1);
	   	int res1_=DBDX_2022_2_2(T1);		//方法一 
	   	printf("\nres1_:%d\n",res1_);
	   	
	   	char arr2[7]={'1','2','2','3','4','0','3'};
	   	Tree T2=Build_tree(arr2,7);
	   	print_arr_c(arr2,7);
	   	show_tree_target(T2,NULL,0);
	   	int res2=DBDX_2022_2_1(T2);			//方法一
	   	printf("\nres2:%d\n",res2);		 
		int res2_=DBDX_2022_2_2(T2);			//方法二 
	   	printf("\nres2_:%d\n",res2_);
    return 0;
}

测试结果

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以通过递归实现判断二叉树是否对称。对于一棵对称二叉树,它的左右子树也是对称的,因此可以定义一个递归函数,判断左右子树是否对称。 具体实现步骤如下: 1. 定义一个isSymmetric方法,接收一个二叉树的根节点作为参数。 2. 在isSymmetric方法中定义一个helper方法,用于递归判断左右子树是否对称。该方法接收两个节点作为参数,分别表示左右子树的根节点。 3. 判断左右子树的根节点是否为空,如果都为空,则返回true;如果只有一个为空,则返回false。 4. 判断左右子树的根节点的值是否相同,如果不同,则返回false。 5. 分别递归判断左子树的左子树和右子树的右子树是否对称,以及左子树的右子树和右子树的左子树是否对称。 6. 如果所有判断都通过,则返回true。 代码实现如下: ```java public boolean isSymmetric(TreeNode root) { if (root == null) { return true; } return helper(root.left, root.right); } private boolean helper(TreeNode left, TreeNode right) { if (left == null && right == null) { return true; } if (left == null || right == null) { return false; } if (left.val != right.val) { return false; } return helper(left.left, right.right) && helper(left.right, right.left); } ``` 其中,TreeNode表示二叉树的节点,定义如下: ```java class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int val) { this.val = val; } } ``` 可以通过创建一棵对称二叉树一棵对称二叉树,分别进行测试,验证上述代码的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值