This article is participating in the “Java Theme Month – Java Brush questions punch card”, see the activity link for details

preface

As an important data structure, binary tree plays a connecting role in algorithm. It is the extension of array and linked list, and also the basis of graph. So learning binary tree related knowledge is very necessary, and in the relevant operation, binary tree traversal is the most frequent, today to see the binary tree traversal method of 4!

Binary tree data structure

The so-called binary tree refers to a tree structure in which each node has at most two branches. Its branches are usually called “left subtree” and “right subtree”, and their order is fixed and cannot be reversed at will. An example of a binary tree is as follows:

class TreeNode{
    int val;
    / / the left subtree
    TreeNode left;
    / / right subtree
    TreeNode right;
}
Copy the code

The former sequence traversal

Also known as sequential traversal, the root node is visited first, the left subtree is traversed, and the right subtree is traversed again. When traversing the left and right subtrees, the root node is visited first, then the left subtree is traversed, and finally the right subtree is traversed until the binary tree is empty.

Traversal methods are mainly divided into recursive and iterative methods, and their specific implementation is shown as follows.

recursive

public ArrayList<Integer> preOrderReverse(TreeNode root){
    ArrayList<Integer> list = new ArrayList<>();

    preOrder(root, list);

    return list;
}


public void preOrder(TreeNode root, ArrayList<Integer> list){
    if(root ! =null){ list.add(root.val); preOrder(root.left, list); preOrder(root.right, list); }}Copy the code

The iteration

/** * Use stack to iterate, since stack is a kind of first in last out data structure, the output order is middle, left, right *, so we first add the root node to the stack, then add the right subtree, then add the left subtree */
public ArrayList<Integer> preOrderReverse(TreeNode root){
    // stack, first in last out
    Stack<TreeNode> stack = new Stack<>();
    ArrayList<Integer> list = new ArrayList<>();

    if(root ! =null) {/ / into the stack
        stack.push(root);
        while(! stack.empty()){/ / out of the stack
            TreeNode node = stack.pop();
            list.add(node.val);
            // The stack is a first-in, last-out data structure, so the right subtree is entered first, then the left subtree
            if(node.right ! =null){
                stack.push(node.right);
            }

            if(node.left ! =null){ stack.push(node.left); }}}return list;
}
Copy the code

In the sequence traversal

First the left subtree is traversed, then the root node is visited, and finally the right subtree is traversed again. When traversing the left and right subtrees, the left subtree is traversed first, then the root node is visited, and finally the right subtree is traversed until the binary tree is empty.

Traversal methods are mainly divided into recursive and iterative methods, and their specific implementation is shown as follows.

recursive

public ArrayList<Integer> inOrderReverse(TreeNode root){
    ArrayList<Integer> list = new ArrayList<>();

    inOrder(root, list);

    return list;
}


public void inOrder(TreeNode root, ArrayList<Integer> list){
    if(root ! =null){ inOrder(root.left, list); list.add(root.val); inOrder(root.right, list); }}Copy the code

The iteration

/** * prints in left, middle, and right order * so the left subtree is pushed first, then the middle node, and finally the right subtree ** /
public ArrayList<Integer> inOrderReverse(TreeNode root){
    ArrayList<Integer> list = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<TreeNode>();

    TreeNode curr = root;
    while(curr ! =null| |! stack.isEmpty()){// The node is not empty until the stack is pressed
        while(curr ! =null){
            stack.push(curr);
            // Consider the left subtree
            curr = curr.left;	    
        }

        // The node is empty
        curr = stack.pop();
        // Add the current value
        list.add(curr.val);
        // Consider the right subtree
        curr = curr.right;
    }
    return list;
}
Copy the code

After the sequence traversal

After traversal first traverses the left subtree, then traverses the right subtree, finally visits the root node, traverses the left and right subtree, still traverses the left subtree first, then traverses the right subtree, finally traverses the root node, until the binary tree is empty, returns!

Traversal methods are mainly divided into recursive and iterative methods, and their specific implementation is shown as follows.

recursive

public ArrayList<Integer> postOrderReverse(TreeNode root){
    ArrayList<Integer> list = new ArrayList<>();

    postOrder(root, list);

    return list;
}


public void postOrder(TreeNode root, ArrayList<Integer> list){
    if(root ! =null){ postOrder(root.left, list); postOrder(root.right, list); list.add(root.val); }}Copy the code

The iteration

public ArrayList<Integer> postOrderReverse(TreeNode root){
    List<Integer> list = new ArrayList<Integer>();
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode current = root;
    // It is used to tell whether the previous node has been accessed
    TreeNode last = null;  
    while(current ! =null| |! stack.isEmpty()){// To the far left of the tree
        if(current ! =null){    
            stack.push(current);
            current = current.left;
        }else{
            // See if the most left node has a right subtree
            current = stack.peek();    
            if(current.right ! =null&& current.right ! = last){ current = current.right; stack.push(current);// Right subtree to the left
                current = current.left;     
            }else{
                // Access the node and mark it as accessed
                current = stack.pop();    
                list.add(current.val);
                last = current;
                current = null; }}}return list;
}
Copy the code

Level traversal

Hierarchical traversal, also known as breadth-first traversal, gives priority to the node closest to the root node and is usually implemented using queues.

Traversal methods are mainly divided into recursive and iterative methods, and their specific implementation is shown as follows.

recursive

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> lists = new ArrayList<List<Integer>>();
    if(root ! =null) {// The root node is not null, recursive
        dfs(1, root, lists);
    }
    return lists;
}


// index: number of layers
public void dfs(int index, TreeNode root, List<List<Integer>> lists){

    // Add an empty list if the number of sequences in Lists is less than the number of layers
    if(lists.size() < index){
        lists.add(new ArrayList<Integer>());
    }

    // Then add the current node to the subsequence of Lists
    lists.get(index - 1).add(root.val);

    // This completes the root node
    +1 = +1 +1 = +1 +1

    if(root.left ! =null){
        dfs(index + 1, root.left, lists);
    }

    if(root.right ! =null){
        dfs(index + 1, root.right, lists); }}Copy the code

The iteration

ArrayList<ArrayList<Integer>> levelOrder(TreeNode root){
    List<List<Integer>> res = new ArrayList<>();
    Queue<TreeNode> queue = new ArrayDeque<>();

    if(root ! =null) {
        queue.add(root);
    }

    while(! queue.isEmpty()) {// Get the length of the current queue, which is equal to the number of nodes in the current layer
        int n = queue.size();
        // Take all the elements of the queue (i.e. the nodes of this layer) and place them in a temporary list
        // If the left/right subtree of the node is not empty, it is queued
        List<Integer> level = new ArrayList<>();
        int i = 0;
        while(i < n){
            TreeNode node = queue.poll();
            level.add(node.val);
            if(node.left ! =null) {
                queue.add(node.left);
            }
            if(node.right ! =null) {
                queue.add(node.right);
            }
            i++;
        }

        // Add the temporary list to the final return result
        res.add(level);
    }

    return res;
}
Copy the code

conclusion

The above is the data structure binary tree traversal 4 kinds, if you have more about the implementation of various traversal, welcome to leave a message!