二叉树的下一个节点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
对于给定的任意一个节点,这个节点都有两种情况
- 有右节点。这种情况下,从这个节点的右节点出发,一直沿着指向左节点的指针往下走
- 没有右节点,这种情况下首先要判断有没有父节点
- 没有父节点了,说明这个节点是整个树的根节点,发生这种情况有两种可能
- 一是输入的就是根节点,并且根节点没有右子节点
- 二是由下面的循环一直往上找,找到了根节点。
- 这两种情况的返回值都是null
- 有父节点,那么就判断当前这个节点与父节点的关系
- 这个节点是父节点的左节点,那么父节点就是中序遍历的下一个节点
- 这个节点是父节点的右节点,那么从父节点出发,重新进行有没有父节点的判断。
- 没有父节点了,说明这个节点是整个树的根节点,发生这种情况有两种可能
在这个题目中,我犯了两个错误导致解题时间过长、代码冗余。
第一个错误就是没有搞清楚判断的优先级。在给定一个节点之后,判断优先级最高的是:这个节点有没有右节点,而不是判断这个节点与父节点的关系。只要这个节点有右节点,不管其有没有父节点,与父节点的关系,都要从右节点出发,找最后一个左节点。
第二个错误是说,在判断节点与父节点关系的时候,首先要判断父节点是否存在,如果父节点不存在,则判断等式根本就不成立,会出现 NullPointerException,也就是说父节点为null,null.left导致了错误。
根据这个思路,如果这道题是给出先序遍历或者后序遍历,该如何解?
先序遍历的话,
- 有左子节点,则直接返回左子节点
- 没有左子节点,有右子节点,则返回右子节点
- 如果是叶子节点的话,
- 没有父节点,返回null
- 有父节点,判断当前节点与父节点的关系
- 这个节点是父节点的左节点,判断父节点是否有右节点
- 这个父节点有右节点,那么返回父节点的右节点
- 这个父节点没有右节点,那么就从父节点出发,进行有没有父节点的判断
- 这个节点是父节点的右节点,那么就从父节点处罚,进行有没有父节点的判断
- 这个节点是父节点的左节点,判断父节点是否有右节点
后续遍历有些不同,他不需要判断这个是否有左右子节点,判断这个节点与父节点的关系
- 有没有父节点,没有返回null
- 节点是父节点的右节点,则直接返回父节点
- 节点是父节点的左节点,判断父节点是否有右节点
- 没右节点,则返回父节点
- 有右节点,则从右节点出发,一直找最左的子节点
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode){
if(pNode == null){
return null;
}
if(pNode.right != null){
pNode = pNode.right;
while(pNode.left != null){
pNode = pNode.left;
}
return pNode;
}
while(pNode.next != null){
if(pNode == pNode.next.left){
return pNode.next;
}else if(pNode == pNode.next.right){
pNode = pNode.next;
}
}
return null;
}
}
测试用例
- 普通二叉树:完全二叉树,不完全二叉树
- 特殊二叉树:
- 所有节点都没有右子节点
- 所有节点都没有左子节点
- 只有一个节点的二叉树
- 二叉树的根节点指针为null
- 不同位置的节点的下一个节点
- 下一个节点为当前节点的右子节点、右子树的最左节点、父节点、跨层父节点
- 当前节点没有下一个节点