1. 程式人生 > >C++ 推斷一棵二叉樹是否對稱

C++ 推斷一棵二叉樹是否對稱

ack iostream 們的 log data 簡單 src -a nbsp

一棵二叉樹對稱,就是說它假設以根為軸,翻轉過去一樣。例如以下圖所看到的,以虛線為軸。把左邊翻轉到右邊,各頂點及頂點中的值一一相應。

技術分享

註意,它並不要求單獨看子樹的時候子樹也是對稱的,例如以下圖,單獨看左子樹時,左子樹是不正確稱的,單獨看右子樹時。右子樹也是不正確稱的,但這棵本身是對稱的。

技術分享

要推斷一棵二叉樹是否對稱,那就是推斷它的左子樹翻轉過去是否和右子樹一樣,註意這裏的“一樣”包含了值也一樣。

以下給出代碼,當中的樣例中的樹,就是第一張圖中的那棵樹:

#include <iostream>
using namespace std;

 struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
    bool isSymmetric(TreeNode *root) {
		if(root==NULL)//假設樹為空,對稱。返回
			return true;
		return mySymmetric(root->left,root->right);//否則推斷以root為根時。左子樹翻轉後是否和右子樹一樣
    }
	bool mySymmetric(TreeNode *leftChild,TreeNode *rightChild) {
		if(leftChild==NULL && rightChild==NULL)//左右子樹都為空,對稱
			return true;
		else if(leftChild!=NULL && rightChild==NULL || leftChild==NULL && rightChild!=NULL){//一個空一個非空,則不正確稱
			return false;
		}else{
		//否則,再推斷
			if(mySymmetric(leftChild->left,rightChild->right) //(1)leftChild的左子樹和rightChild的右子樹對稱嗎?
				&& mySymmetric(leftChild->right,rightChild->left) //(2)leftChild的右子樹和rightChild的左子樹對稱嗎?
				&& leftChild->val==rightChild->val){ //(3)leftChild和rightChild的值一樣嗎?
					return true;//三個條件都滿足,對稱
			}else
				return false;//否則不正確稱
		}
    }
};
int main()
{
	//樣例
	TreeNode root(1);
	TreeNode leftChild(2);
	TreeNode rightChild(2);
	TreeNode leftLeftChild(3);
	TreeNode leftRightChild(4);
	TreeNode rightLeftChild(4);
	TreeNode rightRightChild(3);
	root.left=&leftChild;
	root.right=&rightChild;
	leftChild.left=&leftLeftChild;
	leftChild.right=&leftRightChild;
	rightChild.left=&rightLeftChild;
	rightChild.right=&rightRightChild;
	Solution s;
	if(true==s.isSymmetric(&root))
		cout<<"對稱"<<endl;
	else
		cout<<"不正確稱"<<endl;
	system("pause");
	return 0;
}

以下通過幾個簡單的圖來說明一下。

mySymmetric(leftChild->left,rightChild->right)是計算下圖中藍色方框的部分是否關於對稱軸對稱:
技術分享
mySymmetric(leftChild->right,rightChild->left)是計算下圖中藍色方框的部分是否關於對稱軸對稱:

技術分享

別忘了還要比較它們的值是否相等~

技術分享

C++ 推斷一棵二叉樹是否對稱