1、对称二叉树
1.1 题目:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
1.2 原理:需要注意的是,题目中同样的理解,必须是结构一样,且对应节点的值也要是一样的。遍历的思想,对于根节点的左右子树可以分别将其看成两个二叉树1和树2,同时遍历两个二叉树,只要对应的值相当,每次遍历中比较树1的左节点与树2的右节点,树1的右节点和树2的左节点,核心在这里,保证对称关系。
1.3 代码:
// 遍历二叉树
bool pre(TreeNode* p1, TreeNode* p2)
{
if(p1&&p2)
{
if(p1->val==p2->val)
return pre(p1->left, p2->right)&&pre(p1->right, p2->left);
else
return false;
}
else
{
// p1和p2都是NULL
if(p1==p2)
return true;
else
return false;
}
}
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if(pRoot==NULL)
return true;
TreeNode* pL = pRoot->left;
TreeNode* pR = pRoot->right;
return pre(pL, pR);
}
};
1.4 总结:
(1)在意这种双二叉树同时遍历的这种做法,本质上和普通的二叉树的遍历是没有区别的,只不过每次的访问节点,同时访问了另个节点。
(2)镜像二叉树和原二叉树的区别和联系。主要是对称的。
2、二叉树的下一个结点
2.1 题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
2.2 原理:由于是中序遍历,所以不要管左子树了,因为访问到当前的结点的时候,其左子树如果存在一定已经被访问过了。因此可以分为以下几张情况:
(1)当前节点的右子树存在:直接返回其右子树的最左的节点指针即可。
(2)当前节点的右子树不存在:这种情况较为复杂,再分为两种情况讨论。
1、当前节点是其父节点的左子树,那么下一个要访问的就是其父节点
2、当前节点是其父节点的右子树,这种情况最复杂,需要继续回溯其父节点,只到找到其是父节点的左子树为止。
2.3 代码:
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(pNode==NULL)
return NULL;
//当前节点的右子树不存在
if(pNode->right==NULL)
{
if(pNode->next==NULL)
return NULL;
else
{
//当前节点是左子树
if(pNode->next->left==pNode)
return pNode->next;
else //右子树
{
TreeLinkNode *p = pNode;
while((p->next)&&(p->next->right==p))
p=p->next;
return p->next;
}
}
}
//当前节点的右子树存在
else
{
//找到右子树的最左节点返回
TreeLinkNode *p = pNode->right;
while(p->left)
p = p->left;
return p;
}
return NULL;
}
};
2.4 总结和注意:
1、这种复杂且多样情况的二叉树的问题,一定注意沉下心来,一点点分析,吧各种可能出现的情况想清楚以及对应的解决思路,先自己的在草稿纸上画一画,想清楚,切记不动笔直接空想,多种情况按顺序进行区别。
2、涉及到二叉树的问题,一定注意判断指针的存在性,只有指针存在了,才能对其节点进行操作,这是关键中的关键,编程上的注意。