对称二叉树判断

目录

什么是对称二叉树

 递归

迭代


 

什么是对称二叉树

        一棵对称二叉树,对于根节点而言,他的左子树和他的右子树完全镜像对称,也就是说

                left->left=right->right;

                left->right=right->left;

        那就有两种对称:

  1. 结构对称,即不用看对称节点的数据是否相等,只需要看对称的节点是否存在即可
  2. 数据对称,即不仅要结构对称,其数据也要相同。

 递归

对于递归而言,我们不妨将对称二叉树拆分成子问题,对于根节点的左右节点,我们将这棵树拆成两棵树,一棵以根节点的左孩子为根节点,一棵以根节点的右孩子为根节点,这样我们就可以比较这棵树相对于的节点了。

 那在什么情况下返回false呢?

  1. 一者为NULL,一者不为NULL
  2. 一者数据不等于另一者数据

那在什么情况下返回true呢?

  1. 二者都为NULL
  2. 二者都不为NULL且二者数据相同 

在这里我们可以注意到,我们要比较两个对应节点的数据,即left->date。

但是在我们的情况讨论中,节点是存在为NULL的可能性的,为了不操作空指针,我们必须将NULL的判断放在数据判断的前面。 

那什么时候递归呢?

当然是二者连数据也一样的情况下,此时,我们需要调用自己,参数为左根的左节点与右根的右节点;左根的右节点与右根的左节点。(注意必须对称) 

同时,在归的过程中,只要存在false,那最终结果就是false,所以我们需要用到&&

class com
{
public:
	//确定返回值和参数
	bool compare(treenode* left, treenode* right)
	{
		//确定终止条件
		
		if (NULL != left && NULL == right)return false;
		else if (NULL == left && NULL != right)return false;//注意是else if//因为前面一旦判断,后面就不用看了//前面如果是空指针,那下面的数据比较就会操作空指针
		else if (NULL == left && NULL == right)return true;
		else if (left->a != right->a)return false;
		//此时就是左右节点都不为空且数值相等的情况;
		//此时才做递归,进行下一层的判断
		bool outside = compare(left->left, right->right);
		bool inside = compare(left->right, right->left);
		bool issame = outside && inside;
		
		return issame;
	}
public:
	bool issymmetric(treenode* root)
	{
		if (NULL == root)
			return true;
		return compare(root->left, root->right);
	}
};


迭代

 在这里我们依旧把树拆成左树和右树。

在这里有点类似于层序遍历,只不过我们入队列,入的是对称的镜像节点,队列最前端的两个成员是需要比较的两个镜像成员,对于这个队列,我们每次两两比较队列头的前两位,比较完后并录入这两位相对的子镜像节点。

所以在这里我们需要录入NULL,不然依照我们比较队列前两位的方法,比较的两位就不会是正确相对应的镜像节点了。

但是这时候就会有疑问了,如果录入了NULL,那到时候录NULL的左右子节点的时候不会操作空指针吗?

其实是不会的,我们并不会走到那一步

  1. 如果一者为NULL,一者不为NULL,那程序会直接结束并返回一个false
  2. 如果二者都为NULL,那我们会把这种情况拿出来讨论,不会录入其子节点。

整体代码如下: 

//迭代实现对称二叉树判断
class ISSAME
{
public:
	//确定函数返回值和函数参数
	bool isSame(treenode* root)
	{
		queue<treenode*> que;
		que.push(root->left);
		que.push(root->right);
		while (1)
		{
			if (que.empty())//函数结束,虽然NULL入队列,但是在这里NULL为对象时会contine跳过本次循环,所以不会操作到NULL的left指针或right指针
				break;
			treenode* leftnode = que.front(); que.pop();
			treenode* rightnode = que.front(); que.pop();
			//确定终止条件,即不相同的情况
			if (leftnode == NULL && right != NULL)return false;
			else if (leftnode != NULL && right == NULL)return false;
			else if (leftnode == NULL && right == NULL)continue;//注意这里是contine,即继续向下“递”
			else if (leftnode->a != rightnode->a)return true;
			//接下来的情况就是二者数值相同的情况了,需要继续入队列
			que.push(leftnode->left);//加入左节点的左孩子
			que.push(rightnode->right);//加入右节点的右孩子
			que.push(leftnode->right);//加入左节点的右孩子
			que.push(rightnode->left);//加入右节点的左孩子
							//注意上述两两顺序不能变,因为每次比对的是队列头的前两位
		}
		return true;


	}

};

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值