问题分析java
假设须要查找 node 结点的下一个结点,须要考虑三种状况:node
①node 节点有右孩子算法
下一个结点就是以node结点的右孩子为根的子树中的最左下结点。以下图:node=8,它的下一个结点为12.ide
②node 节点没有右孩子时,node节点是其父结点的左孩子。以下图,结点8的下一个结点是结点12this
③node 节点没有右孩子时,node节点是其父结点的右孩子,以下图,结点14 的下一个结点是 结点16spa
如何在一棵二叉树中查找某个结点?指针
能够用先序遍历的思路。可是必定要注意递归的实现---第11行的 return target 是颇有意义的。递归
在每一次的递归调用中,每一个方法都有一个本身的 target 局部变量。若是在这个方法里面找到了目标结点,若是没有 return 返回的话,当递归回退时就会丢失“已找到的目标结点”----即上一层的 find 方法中的target 变量仍是null(尽管在下一层递归中已经找到了目标结点)get
经过第11行的 return 语句,若是在某一层还未找到目标结点,则会继续递归调用下去,若是找到了,在 return 的时候,上一层的find方法的target变量就不会为 null , 从而在最终 find 方法结束时,返回找到的目标结点。hash
1 //采用先序遍历查找值为ele的结点 2 private BinaryNode find(BinaryNode root, int ele){ 3 if(root == null) 4 return null; 5 if(root.ele == ele) 6 return root; 7 BinaryNode target = null; 8 target = find(root.left, ele); 9 if(target == null)//若是左子树中没有值为ele的结点,if成立,在右子树中查找 10 target = find(root.right, ele); 11 return target; 12 }
①第3-4行是应对查找到叶子结点的状况
②第5-6行,是成功查找到了指定结点的状况。(①②相似于先序遍历中的访问根结点)
③第8行,表示先在左子树中查找(相似于先序遍历左子树)
④第9-10行if表示在左子树中未查找到该结点,则查找右子树⑤第11行,返回查找的结点。若返回null,表示未找到
三,代码分析
①node 节点有右孩子
1 if(node.right != null) 2 { 3 BinaryNode current = node.right; 4 while(current.left != null) 5 { 6 current = current.left; 7 } 8 nextNode = current; 9 }
第3行,先定位到node结点的右孩子。
第4行while循环,查找最左下结点
②node 节点没有右孩子时,node节点是其父结点的左孩子
1 else if(node.parent != null){//node结点 是 parent 的孩子 2 if(node.parent.left != null && node.parent.left.equals(node))// node 是 parent 的左孩子 3 nextNode = node.parent;
若是node节点是其父结点的左孩子,那么下一个结点就是node节点的父结点。
③node 节点没有右孩子时,node节点是其父结点的右孩子
1 else{//node 是 parent的右孩子 2 BinaryNode current = node.parent; 3 //一直往着右孩子的父结点指针向上走 4 while(current.parent.right != null && current.parent.right.equals(current)) 5 { 6 current = current.parent; 7 } 8 nextNode = current.parent; 9 }
要注意第4行while循环中的第一个条件:current.parent.right != null
为何不要判断 current.parent != null 呢?由于在前面的if语句中已经判断了(if(node.parent != null)
完整代码:
public class BSTNextNode {
private class BinaryNode{
int ele;
BinaryNode left;
BinaryNode right;
BinaryNode parent;
int hash;//cache hashCode
public BinaryNode(int ele) {
this.ele = ele;
parent = left = right = null;
}
@Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(!(obj instanceof BinaryNode))
return false;
BinaryNode node = (BinaryNode)obj;
return node.ele == this.ele;
}
@Override
public int hashCode() {// 参考《effective java》中覆盖equals方法
int result = hash;
if(result == 0){
result = 17;
result = result*31 + ele;
hash = result;
}
return result;
}
或者:
下面是该算法的实现代码(已正确处理结点为空的状况)
public TreeNode inorderSucc(TreeNode n)
{
if(n==null) return null;
/*
找到右子结点,则返回右子树里最左边的结点
*/
if(n.right!=null)
{
return leftMostChild(n.right);
}
else
{
TreeNode q=n;
TreeNode x=q.parent;
//向上直至位于左边而不是右边
while(x!=null&&x.left!=q)
{
q=x;
x=x.parent;
}
return x;
}
}
public TreeNode leftMostChild(TreeNode n)
{
if(n==null)
return null;
while(n.left!=null)
{
n=n.left;
}
return null;
}
或者