問題分析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;
}
或者