二分木の3つの非再帰的走査
1.バイナリツリーの事前順序付けの非再帰的トラバーサル実装(スタックを使用)
- アイデア:(スタックを使用)
1。curが空でない場合は、最初にツリーのルートをcurでマークします
。2。ルートを直接印刷し、cur(つまり、ルート)をスタックにプッシュします。3
。次に、 rootの左側のサブツリーは、左にトラバースされています
。4。ループが発生すると、左端のノードがスタックに配置されます
。5。この時点では、キューは空ではありません(これは最も外側の状態です)。ループ)、それがポップされます行のhead要素、およびポップアップ要素
の右側のノードをcurでマークします; 6.したがって、右側のノードが空でない場合は、右側のノードを印刷してスタックにプッシュする必要があります、したがって、条件が最も外側に追加され、右側のノードも出力されます。つまり、curは空ではありません。
void preOrderTraversal1(Node root){
if (root == null)return;
Stack<Node> stack = new Stack<>();
Node cur = root;
while(cur != null || !stack.empty()){
while(cur != null){
System.out.print(cur.val);
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
cur = top.right;
}
}
2.順序どおりの非再帰的トラバーサル
- アイデア:
1。前のシーケンスと同じ原理ですが、最初に左端のノードを見つけ、左のノードを印刷し、次にルートを印刷し、次に右のノードを印刷します。
void inOrderTraversal1(Node root){
if (root == null)return;
Stack<Node> stack = new Stack<>();
Node cur = root;
while(cur != null || !stack.empty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
System.out.print(top.val);
cur = top.right;
}
}
3.注文後の非再帰的トラバーサル
- アイデア:
1。ポストオーダートラバーサルもcurを使用して、ノードを1つずつ検索し、最後の左側のノードにプッシュしてから、スタックをポップアウトし、左側のノードを出力します
。2。次に、右側のノードがあるかどうかを判断します。右側のノードが空の場合は、ルートを直接印刷します
。3。ただし、エラーが発生するため、後でノードが繰り返し印刷される場合に備えて、印刷されたノードをprevでマークする必要があります
4次の図のように、マークを付けない場合、ノード「H」が印刷されたが、最初に「E」を印刷する必要があり、その右側のノードが見つかった場合(cur .right)が空ではなかった場合、「H」が再びスタックに配置されるため、マークを付ける必要があります。cur.right== prevの場合、ルートは直接出力され、下に移動する必要はありません。正しいノードを印刷します。これにより、ifステートメントを入力してルートノードを印刷できます。
void postOrderTraversal1(Node root){
if (root == null)return;
Stack<Node> stack = new Stack<>();
Node cur = root;
Node prev=null;
while(cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.peek();
if (cur.right == null || cur.right == prev) {
stack.pop();
System.out.print(cur.val);
prev = cur;
cur = null;
} else {
cur = cur.right;
}
}
}