アルゴリズム通関村 - バイナリ ツリーの事前順序、順序どおり、および順序後のトラバースを反復的に実現します。

1. プリオーダー、インオーダー、ポストオーダーでの再帰的書き込み

プロローグ

public void preorder(TreeNode root, List<Integer> res) {
    
    
        if (root == null) {
    
    
            return;
        }
        res.add(root.val);
        preorder(root.left, res);
        preorder(root.right, res);
    }

その後

public static void postOrderRecur(TreeNode head) {
    
    
    if (head == null) {
    
    
        return;
    }
    postOrderRecur(head.left);
    postOrderRecur(head.right);
    System.out.print(head.value + " ");
}

順番通りに

public static void inOrderRecur(TreeNode head) {
    
    
    if (head == null) {
    
    
        return;
    }
    inOrderRecur(head.left);
    System.out.print(head.value + " ");
    inOrderRecur(head.right);
}

2. プレオーダートラバーサル反復法

事前順序トラバーサルの主な特徴は、中央、左、右です。
ここに画像の説明を挿入
上記の事前順序トラバーサルは、1 2 4 5 3 6 7 です。1
2 4 がすべて左側のサブツリーであり、次に右側のサブツリーであることは明らかです。トラバーサル後にサブツリーに到達するため、反復で行う必要があるのは、左側のサブツリー ノードのトラバースを維持し、現在の左側のサブツリーのルート ノードを保存することです。左側のサブツリーは終了し、ノードを削除して右側のサブツリーを見つけます。ノード。ここでは、スタックを使用してノードを保存し、対応する順序でノードをポップする必要があります。

2.1 バイナリツリーの事前順序走査

バイナリ ツリーの事前順序トラバーサル
バイナリ ツリーのルート ノード ルートが与えられた場合、そのノード値の事前順序トラバーサルを返します。
入力: root = [1,null,2,3]
出力: [1,2,3]
ここに画像の説明を挿入

 public List<Integer> preorderTraversal(TreeNode root) {
    
    
      List<Integer> res = new ArrayList<>();
      if(root == null)  return res;
      Deque<TreeNode> stack = new LinkedList<>();
      TreeNode node = root;
      while(!stack.isEmpty() || node!=null){
    
    
          while(node!=null){
    
    
              res.add(node.val);
              // 保存根节点,找到对应的右节点
              stack.push(node);
              // 处理左子树
              node = node.left;
          }
          // 找到对应的右节点的根节点
        node = stack.pop();
        // 处理右子树
        node=node.right;
      }
      return res;
    }

3. 反復的な順序トラバーサル

特徴: 左、中央、右
ここに画像の説明を挿入
要素: 4 2 5 1 6 3 7
これは、毎回左端のサブツリー ノードを走査し、ルート ノードにまだ右のノードがある場合は、逆の順序で一番下のノードを出力すると見ることができます。右に入力し続けると、ノードは一番下に移動します。それ以外の場合は、逆の順序で出力されます。このノードを保存するにはスタックを使用する必要があります。

3.1 二分木のインオーダートラバース

バイナリ ツリーの順序トラバーサル
バイナリ ツリーのルート ノード ルートを指定すると、その順序トラバーサルを返します。

入力: root = [1,null,2,3]
出力: [1,3,2]

通常は同じですが、追加する場合、追加される現在のリンクの最後のノード要素となる点が異なります。

    public List<Integer> inorderTraversal(TreeNode root) {
    
    
        List<Integer> res = new ArrayList<>();
        if(root ==null) return res;
        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode node = root;
        while(!stack.isEmpty() || node!=null){
    
    
            while(node!=null){
    
    
                stack.push(node);
                node=node.left;
            }
            // 此时已经到头了
            node = stack.pop();
            res.add(node.val);
            node=node.right;
        }
        return res;
    }

4. ポストオーダートラバーサル

特徴: 左、右、中央
ここに画像の説明を挿入
要素: 4 5 2 6 7 3 1
要素の特徴: 現在のルート ノードの 2 つの子ノードの値を出力し、次にルート ノードを出力する必要があります。しかし、実際の操作では、事後注文の便利な要素を 1 3 7 6 2 5 4 に反転するのは非常に面倒です。これは事前注文と似ていますが、違いは、事前注文が左を横切ることです。最初にノードを探索し、今度は右のノードをトラバースしてから、リスト要素全体を反転する必要があります。

4.1 二分木の事後走査

バイナリ ツリーの事後探索
バイナリ ツリーのルート ノード ルートを指定すると、そのノード値の事後探索を返します。

 public List<Integer> postorderTraversal(TreeNode root) {
    
    
        List<Integer> res = new ArrayList<>();
        if(root == null) return res;
        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode node = root;
        while(!stack.isEmpty() || node!=null){
    
    
            while(node!=null ){
    
    
                res.add(node.val);
                stack.push(node);
                node= node.right;
            }
            node =  stack.pop();
            node = node.left;
        }
        Collections.reverse(res);
        return res;
    }

ただし、この方法では、関連する事後順序トラバーサル機能は使用されず、事前順序のみが使用されます。

4.2 反復法

public List<Integer> postorderTraversal(TreeNode root) {
    
    
        List<Integer> res = new ArrayList<>();
        if(root == null) return res;
        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode node = null;
        while(!stack.isEmpty() || root!=null){
    
    
            while(root!=null ){
    
    
                stack.push(root);
                root= root.left;
            }
            root =  stack.pop();
            // 如果右子树为空或者已经被访问过了,才能添加当前节点值
            if(root.right==null || root.right == node){
    
    
                res.add(root.val);
                node=root;
                root=null;
            }else{
    
    
                stack.push(root);
                root = root.right;
            }
        }
        return res;
    }

この方法は少しわかりにくいですが、関連する手順も理解できます。

Supongo que te gusta

Origin blog.csdn.net/qq_52843958/article/details/132064064
Recomendado
Clasificación