バイナリツリーモーリス(モリス)トラバーサル

何モリス横断されます

実際には、バイナリツリートラバーサルアルゴリズムのO(1)にスペースを最適化する複雑。

一般トラバーサルアルゴリズムのために、我々は再び訪問した後、スタックを格納するノードのニーズを使用しています。最悪の場合、我々は全体のバイナリツリーノードを格納する必要があります。したがって、空間の複雑さはO(N)です。O(1)レベルまでの空間の複雑さを横断しながら、モリス吸い込ま。モリスは、「手がかりバイナリツリー」の概念を横断するために使用される、実際には、先行ノードのいくつかの種類を保存したり、後続ノードを横断するリーフノードの周りにNULLポインタを使用することです。だから、追加のスペースがありません。

モリスは、トラバーサルアルゴリズムを考えました

現在のノードがCURであり、開始時にルートルートに割り当てられたと仮定する。

  1. ノードが空CURであるかどうかを決定します
  2. 空でない場合は
    なし左の子CUR場合は1)、CUR更新権、すなわち(CUR = cur.right)
    2)CUR左の子がある場合は、子はノード前を見つけるために、右端ツリーのに任されています
    • 前空、そして右の子の右の子はCURを指している場合。pre.right = CUR
    • 子供が右の前curがある場合、空を指しています。pre.right = nullを。(ツリー構造を減らします)
  3. curが空で、散歩を停止

予約注文トラバーサルモリス

簡潔には、プロセスを横断する前にモリスを説明し、単純なバイナリツリーの例として、以下を取ります。
ここに画像を挿入説明

  • ルート・ノード1は、CURに設定されています。
  • 左の子ノードCUR(ノード1)が空にされていないため、私たちは右端のノード5とノード2に左側のサブツリーのルートノードを見つけるようCUR(ノード1)2は、空ではありません。
  • 5右の子ノードが空である場合、CUR値出力(ノード1)、および右の子ノード、我々は5 CUR、すなわちAノードを指摘しました。左の子ノードCUR更新CUR、そのノード2。
  • CUR(ノード2)子供が空のままにされていないため、その左サブツリー右端ノード4を発見
  • 4右の子ノードは、第1の出力値のCUR(ノード2)、及び右の子ノード4点CUR(ノード2)が空であり、その左の子ノード4にCUR(ノード2)を更新します。
  • この時間CUR(ノード4)は、子供が、我々はCURノード2を更新しますので、自分の子供にアクセスする権利ので、子供は、ノード2に右のポイントを発見し、空のままにされます。
  • 、今回は、左の子ノード4は、我々は再び左部分木の右端のノード4を見つける空でないノード2にターンポイントでそのCURを見つけるが、今回はノード右の子はCURの4点は、我々はそれを削除しますので、右の子ノード4へのポイントが空であることを、オリジナルのツリー構造を復元します。そしてので、子供たちが訪問し、ルートノードを残したので、今回はその右の子ノード5を訪問しています。
  • ...
public void Morris_preorderTraversal(TreeNode root){
    TreeNode cur = root;
    while(cur!=null){
        if(cur.left!=null){
            TreeNode pre = cur.left;
            while(pre.right!=null && pre.right!=cur){
                pre = pre.right;
            }
            if(pre.right == null){	// 第一次到达左子树的最右端
                System.out.print(cur.val);
                pre.right = cur;
                cur = cur.left;
            }
            else{ // 第二次到达左子树的最右端
                pre.right = null;
                cur = cur.right;
            }
        }
        else{
            System.out.print(cur.val);
            cur = cur.right;
        }
    }
}

モリス予約限定!

モリスとトラバーサルシーケンス前順トラバーサル以下は、出力は、位置の変化を表示されます。

public void Morris_inorderTraversal(TreeNode root){
        TreeNode cur = root;
        while(cur!=null){
            if(cur.left!=null){
                TreeNode pre = cur.left;
                while(pre.right!=null && pre.right!=cur){
                    pre = pre.right;
                }
                if(pre.right == null){
                    pre.right = cur;
                    cur = cur.left;
                }
                else{
                    pre.right = null;
                    System.out.print(cur.val);
                    cur = cur.right;
                }
            }
            else {
                System.out.print(cur.val);
                cur = cur.right;
            }
        }
    }

モリス順トラバーサルの後

この後順モリスは最も複雑です。子どもたちは、ルートノードの前に右の出力を必要とするので。図については、ときに後順トラバーサル順序:4,5,2,6,3,1。私たちは長い順トラバーサル後のアクセス順序を達成することができ、我々は逆出力、などとして、2と5が右の境界であるノード、左側のサブツリーノード1に見ることができます。したがって、我々はノード2に、そのノード5点を反転する機能を必要とします。そしてその後、(ツリーの構造を変更せずに)バック反転された出力、後。
ここに画像を挿入説明

public TreeNode reverseNode(TreeNode node){
    TreeNode pre = null;
    TreeNode next = null;
    while(node!=null){
        next = node.right;
        node.right = pre;
        pre = node;
        node = next;
    }
    return pre;
}

public void printNode(TreeNode node){
    TreeNode tail = reverseNode(node);
    TreeNode cur = tail;
    while(cur!=null){
        System.out.println(cur.val);
        cur = cur.right;
    }
    reverseNode(tail);
}

public void Morris_postorderTraversal(TreeNode root) {
    TreeNode cur = root;
    while(cur != null){
        if(cur.left!=null){
            TreeNode pre = cur.left;
            while(pre.right!=null && pre.right!=cur){
                pre = pre.right;
            }
            if(pre.right==null){
                pre.right = cur;
                cur = cur.left;
            }
            else{
                pre.right = null;
                printNode(cur.left);
                cur = cur.right;
            }
        }
        else{
            cur = cur.right;
        }
    }
    printNode(root);
}

概要

O(1)までの空間の複雑さのバイナリツリートラバーサルを横断モリスは、当然のことながら、依然として時間の複雑さはO(N)です。

リリース5元の記事 ウォンの賞賛0 ビュー100

おすすめ

転載: blog.csdn.net/danmo_wuhen/article/details/104339630