私はバイナリツリー(BSTではない)の順序トラバーサル(パンキャッキングとも呼ばれます)について少し前に取り上げたアカデミックコースからの次のテキストを持っています:
Inorderツリートラバーサル
木の外側に線を引きます。ルートの左側から開始し、ツリーの外側を回って、ルートの右側に到達します。できるだけ木に近づきますが、木を越えないでください。 (ツリー-その枝とノード-を堅固な障壁として考えてください。)ノードの順序は、この線がその下を通過する順序です。ノードの「下」に移動するタイミングがわからない場合は、常に「左側」のノードが最初に来ることに注意してください。
使用した例を以下に示します(下とは少し異なるツリー)
しかし、Googleで検索すると、矛盾する定義が表示されます。たとえば wikipedia example :
順序トラバーサルシーケンス:A、B、C、D、E、F、G、H、I(左子、ルートノード、右ノード)
しかし、定義#1(私の理解)によれば、これは
A、B、D、C、E、F、G、I、H
誰がどの定義が正しいかを明確にできますか?どちらも異なるトラバーサルメソッドを説明している可能性がありますが、たまたま同じ名前を使用しています。査読済みの学術テキストが間違っているとは信じられませんが、確信が持てません。
絵を描くのが苦手だったのですが、どのように選ぶかを示した順番です。
描画される線の真上にあるノードをほぼ選択します。
定義を忘れてください。アルゴリズムを適用する方がはるかに簡単です。
void inOrderPrint(Node root)
{
if (root.left != null) inOrderPrint(root.left);
print(root.name);
if (root.right != null) inOrderPrint(root.right);
}
たった3行です。事前注文と事後注文の順序を並べ替えます。
注意深く読むと、最初の「定義」がルートのleftを開始するように言っており、ノードの順序はnderを渡すときに決定されます。したがって、B
は最初のノードではありません。左からA
に渡してから、最初にnderA
を渡してから、上に移動してnderB
を渡します。したがって、両方の定義で同じ結果が得られるようです。
私が個人的に見つけた この講義 非常に役に立った。
a
のルートを持つ最初のバイナリツリーは、正しく構築されていないバイナリツリーだと思います。
ツリーの左側がすべてルートより小さく、ツリーのすべての右側がルート以上になるように実装してください。
適切なトラバーサルは、次のとおりです。リーフノード(ルートノードではない)を使用して可能な限り左
Fはルートまたは左です。よくわかりません
どちらの定義でも同じ結果になります。最初の例のletterにだまされないでください-パスに沿った数字を見てください。 2番目の例では、パスを示すのに文字を使用しています。おそらくそれが原因であなたを失っています。
たとえば、最初のツリーのアルゴリズムを使用して2番目のツリーをトラバースする方法を示す順序の例では、「B」の後に「D」を配置しますが、左側の子ノードがまだあるため、そうしないでください。 Dが利用可能(それが最初の項目が「この行が通過する順序下それら」)と言う理由です。
これは遅いかもしれませんが、後で誰にとっても役立つ可能性があります.. uダミーまたはnullノードを無視する必要はありません。たとえば、Node Gは左nullノードを持っています..このnullノードを考慮すると、すべてのことを行います大丈夫..
しかし、定義#1(私の理解)によれば、これは
A, B, D, C, E, F, G, I, H
残念ながら、あなたの理解は間違っています。
ノードに到着したときはいつでも、現在のノードを見る前に、利用可能な左側のノードに降りてから、利用可能な右側のノードを調べる必要があります。 Cの前にDを選択した場合、最初に左側のノードに降下しませんでした。
void
inorder (NODE root)
{
if (root != NULL)
{
inorder (root->llink);
printf ("%d\t", root->info);
inorder (root->rlink);
}
}
これは、順序トラバーサルを再帰的に定義する最も簡単な方法です。この関数をメイン関数で呼び出して、特定のバイナリツリーの順序トラバーサルを取得します。
私によれば、ウィキで述べられているように、インオーダートラバーサルのシーケンスは左ルート右です。
A、B、C、D、E、Fまでは、すでに理解していると思います。今度はルートFの次のノードはGで、左のノードではなく右のノードを持っているため、ルール(左ルート右)のnull-g右に従います。今、私はGの右ノードですが、左ノードがあるので、トラバーサルはGHIになります。これは正しいです。
お役に立てれば。
パッケージデータ構造;
パブリッククラスBinaryTreeTraversal {
public static Node<Integer> node;
public static Node<Integer> sortedArrayToBST(int arr[], int start, int end) {
if (start > end)
return null;
int mid = start + (end - start) / 2;
Node<Integer> node = new Node<Integer>();
node.setValue(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
return node;
}
public static void main(String[] args) {
int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 };
Node<Integer> node = sortedArrayToBST(test, 0, test.length - 1);
System.out.println("preOrderTraversal >> ");
preOrderTraversal(node);
System.out.println("");
System.out.println("inOrderTraversal >> ");
inOrderTraversal(node);
System.out.println("");
System.out.println("postOrderTraversal >> ");
postOrderTraversal(node);
}
public static void preOrderTraversal(Node<Integer> node) {
if (node != null) {
System.out.print(" " + node.toString());
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
public static void inOrderTraversal(Node<Integer> node) {
if (node != null) {
inOrderTraversal(node.left);
System.out.print(" " + node.toString());
inOrderTraversal(node.right);
}
}
public static void postOrderTraversal(Node<Integer> node) {
if (node != null) {
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(" " + node.toString());
}
}
}
パッケージデータ構造;
パブリッククラスNode {
E value = null;
Node<E> left;
Node<E> right;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
public Node<E> getLeft() {
return left;
}
public void setLeft(Node<E> left) {
this.left = left;
}
public Node<E> getRight() {
return right;
}
public void setRight(Node<E> right) {
this.right = right;
}
@Override
public String toString() {
return " " +value;
}
}
preOrderTraversal >> 4 2 1 3 6 5 7 inOrderTraversal >> 1 2 3 4 5 6 7 postOrderTraversal >> 1 3 2 5 7 6 4
インラインツリートラバーサルの場合、トラバーサルの順序は左ノード右であることに注意する必要があります。競合している上記の図の場合、左側のリーフ(子)ノードを読み取る前に親ノードを読み取ると、エラーが発生します。
適切なトラバーサルは次のようになります:リーフノードで可能な限り左(A)、親ノード(B)に戻り、右に移動しますが、Dにはその子が左にあるため、再び下に移動します(C)、バックアップします。 Cの親(D)に、Dの右の子(E)に、ルート(F)に逆戻りし、右の葉(G)に移動し、Gの葉に移動しますが、左の葉ノードがあるため、そこに移動します(H) 、parent(I)に戻ります。
上記のトラバーサルでは、括弧内にリストされているノードを読み取ります。