バイナリツリーのルートを取得し、ノードのノードを反復処理するJavaイテレータ(つまり、next
およびhasNext
メソッドが必要)を記述する方法in-order fashionのバイナリツリー?
サブツリーの最初の要素は常に左端の要素です。要素の後の次の要素は、その右サブツリーの最初の要素です。要素に適切な子がない場合、次の要素は要素の最初の右祖先です。要素に正しい子も右の祖先もない場合、それは右端の要素であり、反復の最後になります。
私のコードが人間が読めるものであり、すべてのケースをカバーすることを願っています。
public class TreeIterator {
private Node next;
public TreeIterator(Node root) {
next = root;
if(next == null)
return;
while (next.left != null)
next = next.left;
}
public boolean hasNext(){
return next != null;
}
public Node next(){
if(!hasNext()) throw new NoSuchElementException();
Node r = next;
// If you can walk right, walk right, then fully left.
// otherwise, walk up until you come from left.
if(next.right != null) {
next = next.right;
while (next.left != null)
next = next.left;
return r;
}
while(true) {
if(next.parent == null) {
next = null;
return r;
}
if(next.parent.left == next) {
next = next.parent;
return r;
}
next = next.parent;
}
}
}
次のツリーを検討してください。
d
/ \
b f
/ \ / \
a c e g
a
には右の子がないため、次の要素は「左から来るまでアップ」ですb
には適切な子があるため、b
の右サブツリーを反復処理しますc
には正しい子がありません。親はb
で、これはトラバースされています。次の親はd
であり、これは走査されていないため、ここで終了します。d
には正しいサブツリーがあります。その左端の要素はe
です。g
には正しいサブツリーがないため、上に歩きます。右から来たので、f
にアクセスしました。 d
が訪問されました。 d
には親がないため、さらに上に移動することはできません。私たちは右端のノードから来て、繰り返し処理を完了しました。イテレータの次のエントリ 'nextEntry()'を取得するために、Java.util.TreeMap
以下に貼り付けました。平易な英語では、ルートノードが最初にnullでないことを確認してから、nullを返します。そうでない場合、nullでない場合は正しいノードをビストします。次に、左(nullでない場合)にアクセスし、nullがヒットするまでwhileループでその左に繰り返しアクセスします。元の右ノードがnullである場合、すべてではなく、nullでない場合は親ノードにアクセスします。次に、nullになるか、現在アクセスしているノードの右(子)ノードが最後の位置に等しくなるまで、親をビストするwhileループに入ります。座っているエントリを返します。これらすべてのオプションに失敗すると、(元の)ルートノードを返します。 'HasNext()'は、返す「次のエントリ」がnullかどうかを単にチェックします。
public final boolean hasNext() {
return next != null;
}
final TreeMap.Entry<K,V> nextEntry() {
TreeMap.Entry<K,V> e = next;
if (e == null || e.key == fenceKey)
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next = successor(e);
lastReturned = e;
return e;
}
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
if (t == null)
return null;
else if (t.right != null) {
Entry<K,V> p = t.right;
while (p.left != null)
p = p.left;
return p;
} else {
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}