145. Post order traversal of binary tree (iterative traversal)

145. Post order traversal of binary tree

Given a binary tree, return its postorder traversal.

Example:

input: [1,null,2,3]  
   1
    \
     2
    /
   3 

output: [3,2,1]

For post order traversal, because the traversal order is left - > right - > middle, a node cannot be out of the stack immediately after the traversal of its left subtree is completed. Instead, it needs to wait for the traversal of its right subtree before it is out of the stack. How do we know whether the current stack is due to the completion of the traversal of the left subtree or the right subtree?

So we need a new data structure to help record whether the node is out of the stack for the first time or the second time. as follows

 class TagNode{
      TreeNode node;
      boolean flag;

      public TagNode(){}
      public TagNode(TreeNode node ,boolean flag){
         this.node = node;
         this.flag = flag;
      }
  }

You can see that the TagNode contains two fields, one is the node of the tree and the other is the flag field. At first, the flag field is initialized to false,

If the current node is out of the stack due to the completion of the traversal of the left subtree of the current node, we will update the value of this flag field to true, and then push it into the stack. Then, when the node is out of the stack after the traversal of the right subtree is completed, check that the value of the flag bit is true before it can be really out of the stack.

An example is given to illustrate the traversal process of post order traversal of binary tree.

Create a new TagNode for node 1 with false flag and merge it into the stack

Then the pointer moves to the child node of node 1 and is found to be null.

When the element at the top of the stack is out of the stack, check that the flag flag is found to be false, indicating that this is the first time out of the stack. We change the value of flag to true, press this node back into the stack, and then traverse its right subtree.

Then create a tagnode for node 2, set the flag to false, and push it into the stack

Recursively traverse the left subtree until it is null

At this time, the now pointer is null, the top element of the stack is out of the stack, check that the flag value is false, change the flag value to true, press it into the stack again, and then traverse its right subtree.

Then it is found that the value of its right child node is also null. The node is out of the stack again. Check that its flag value is true and meets the requirements of out of the stack. Add its value to the res array and out of the stack.

At this time, now still points to null, so we still need to get an element out of the stack. Therefore, take node 2 out of the stack, check that its flag value is flag, change the flag value to true, press it into the stack again, and then traverse its right subtree.

Unfortunately, at this time, the right subtree of node 2 is still null, so we take node 2 at the top of the stack out of the stack again, check that its flag value is true and meets the requirements for out of the stack, and add its value to the res array to get out of the stack.

At this time, the now pointer still points to null, so it is necessary to pull out a node from the stack again. This node is 1 node. Check that its flag value is true and meets the requirements for pulling out of the stack. After adding its value to the res array, pull the node out of the stack.

At this time, now points to null and there are no stack elements in the stack. The traversal process ends and the required array res is obtained.

The code is as follows:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
  static class TagNode{
      TreeNode node;
      boolean flag;

      public TagNode(){}
      public TagNode(TreeNode node ,boolean flag){
         this.node = node;
         this.flag = flag;
      }
  }
  public List<Integer> postorderTraversal(TreeNode root) {
      List<Integer> res = new ArrayList<>();
      if(root == null){return res;}

      Deque<TagNode> stack = new ArrayDeque<>();
      TreeNode now = root;
      TagNode node ;
      while(now != null || !stack.isEmpty()){
        while(now != null){
          node = new TagNode(now,false);
          stack.push(node);
          now = now.left;
        }

        node = stack.pop();
        if(node.flag == true){
          res.add(node.node.val);
        }else{
          node.flag = true;
          stack.push(node);
          now = node.node.right;
        }
      }
      return res;
    }
}

Summary:

  • Easy to get in and difficult to get out: for a node, as long as the now pointer points to it, it will be put into the stack immediately. If you want to get a node out of the stack, you must check the flag value twice to meet the conditions before it can be put out of the stack.
  • If the flag node value of the out of stack node is false, it means that its right subtree has not been traversed. Update the flag value and push it back into the stack, and the now pointer points to its right subtree instead
  • If the flag node value of the outbound node is true, it indicates that its left and right subtrees have been traversed and meet the outbound conditions.
  • The inner class should be represented as a static class with static.

Tags: Python Algorithm data structure

Posted on Sun, 03 Oct 2021 18:26:02 -0400 by jack bro