1.题目
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
2.code
/*
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)
{
//TreeLinkNode* p=NULL;
//判断pNode有右子树
if(pNode->right!=NULL)
{
TreeLinkNode* p=pNode->right;
while(p->left!=NULL)
p=p->left;
return p;
}
//pNode没有右子树
else
{
TreeLinkNode* pcur=pNode;
TreeLinkNode* pre=pNode->next;
//如果头节点不为空并且当前节点不是左节点就一直沿着父节点找下去
while(pre!=NULL&&pre->right==pcur)
{
pcur=pre;
pre=pre->next;
}
//不为空且是左节点了那么其父节点就是下一个节点 或者是空 表示没有写一个节点了
return pre;
}
}
};
3.分析
- 如果该节点有右子树:那么中序遍历中下一个节点一定是右子树的最左节点;因此只需要一直向左遍历即可。
- 如果该节点没有右子树,那么说明中序遍历中下一个节点应该顺着父节点向上查找,如果找到根节点还没有找到,则表示没有下个节点返回NULL,否则,当向上沿着父节点搜索的路上遇到一个父节点A,是另一个父节点B节点的左节点,那么父节点就是下一个节点。或者说,该节点本来就是某个父节点C的左节点,那么父节点C就是下一个节点,这两种情况可以合并起来。
- 我在写代码的时候,犯了一个错误:那么就是将情况2归为了求解节点的父节点不为空的情况下。其实,是否为空,都不影响,为空,则表示是根节点,根节点的父节点是有定义的,定义为NULL,返回即可。
- 整理一下思路,中序遍历是先遍历左节点,再遍历根节点,最后遍历右节点。如果有一个节点有右子树,那么下一个节点就是其右子树的某一个节点,而在右子树中先遍历到的又是左节点。如果一个节点没有右子树,那么它的下一个节点只能往上找。如果它本身是一个左节点,那么下一个节点就是其父节点。如果本身是一个右节点,那么下一个节点只能向上找,直到当前父节点是其父节点的左节点。如果当前父节点是左节点,那么表示其父节点还没有被遍历到。