JAVA: summary of traversal methods of binary tree: recursive and iterative implementation of depth first traversal, breadth first traversal + pre, middle and post order traversal

1. Main traversal methods of binary tree

(1) Depth first traversal: traversal goes to the depth of the tree and returns when a leaf node is encountered. It can be implemented by recursion or iteration. Recursion is generally used to simulate the process of traversing deep.

        It can be further divided into pre order traversal, middle order traversal and post order traversal.

Preorder traversal: first traverse the intermediate node, then the left node, and finally the right node. (middle left and right)

Similarly, middle order traversal: left, middle and right; Post order traversal: left and right middle.

The judgment skill is: the position of the intermediate node is the traversal order. For example, if the middle node is in the left and right, and the middle node is in the front, it is the front order; Left, middle and right, and the middle node is in the middle, which is the middle order; In the left and right, in the middle, at the end, is the post order traversal.

  For example, this binary tree:

Preorder traversal: [1, 2, 3, 4, 5, 6, 7]

Middle order traversal: [4, 2, 5, 1, 6, 3, 7]

Post order traversal: [4, 5, 2, 6, 7, 3, 1]

(2) Breadth first traversal: start from the root node and traverse layer by layer. It is generally realized by iterative method.

2. Implementation code

  Definition of node class:

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;
  	}
}

(1) Depth first traversal

① Recursive method  

Preorder traversal: Idea: exit the recursive function of this layer when encountering an empty node, and then process the intermediate node, left node and right node accordingly. The intermediate node directly adds to the result set, and then recurses to the left and right in turn.

public List<Integer> preOrderReverse(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preOrder(root, (ArrayList<Integer>) res);
        return res;
    }

    void preOrder(TreeNode root, ArrayList<Integer> res){
        if(root==null){
            return;    //Null node encountered, return
        }
        res.add(root.val);           // Middle: add nodes to the result array
        preOrder(root.left, res);    // Left: traverse the left node of the current node
        preOrder(root.right, res);   // Right: traverse the right node of the current node
    }

The middle order and post order traversal are the same. Just put the processing logic of the intermediate node in the middle and behind the processing logic of the left and right nodes respectively.

② Iterative method

Preorder traversal / postorder traversal: the code of preorder and postorder traversal is similar by iterative method. It needs to be implemented with the help of stack: pre order traversal. The right node enters the stack first and the left node enters the stack later (first in and then out, so it is the opposite of the traversal order).

public List<Integer> preOrderReverse2(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        Stack<TreeNode> stack = new Stack<>();    
        stack.push(root);   //Root node stack first
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            res.add(node.val);    // Middle: node values are added to the result set
            if (node.right!=null) {
                stack.push(node.right);    //Left: right node stack
            }
            if(node.left!=null){
                stack.push(node.left);     //Right: left node stack
            }
        }
        return res;
        }

Middle order traversal: the iterative method of middle order traversal needs to use the traversal of the pointer to access the node and process the elements on the node with the help of the stack.

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = new TreeNode();
        cur = root;    // Initialization pointer: points to the root node
        while(!stack.isEmpty() || cur!=null){
            if(cur!=null){    
                stack.push(cur);
                cur = cur.left;    // Left: iterate to the left leaf node
            }else{
                cur = stack.pop();
                res.add(cur.val);  // Medium: add result set
                cur = cur.right;   // Right: iterate to the leaf node on the right
            }
        }
        return res;

(2) Breadth first traversal

With the help of queues. The elements of each layer are stored in the queue. Each traversal of the queue is equivalent to traversing the elements of one layer of the binary tree. In the process of traversal, the left and right child nodes of the currently traversed node are added to the queue every time. Therefore, after traversing the nodes of this layer, the elements in the queue are the nodes of the next layer.

public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);        // The root node joins the queue first
        while (!queue.isEmpty()){
            int n = queue.size();    //Number of elements in the queue: equal to the number of elements in this layer
            List<Integer> temp = new ArrayList<>();    //temp stores the elements traversed by this layer
            for(int i=0; i<n; i++){
                TreeNode node = queue.poll();
                temp.add(node.val);    // The value of the element traversed by this layer is added to temp
                if(node.left!=null){
                    queue.add(node.left);    // The left node joins the queue
                }
                if (node.right!=null){
                    queue.add(node.right);   // The right node joins the queue
                }
            }
            res.add(temp);
        }
        return res;

Keywords: Java Algorithm data structure

Added by ma5ect on Sat, 02 Oct 2021 23:48:30 +0300