Depth-first traversal DFS non-recursive algorithm understanding and Java implementation (TreeNode tree structure non-array input)

question

Given a class TreeNode, how to traverse it with non-recursive DFS?

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

train of thought

data structure

Non-recursive graph traversal generally uses two data structures, stack and queue. Considering the characteristics of the two data structures, it is not difficult to think that stacking is more suitable for depth-first traversal, and queues are more suitable for breadth-first traversal.

algorithm details

For the depth-first traversal algorithm, I won’t go into details here. To sum it up, DFS is to walk one way and then go to the nearest save point to take another one. BFS looks forward every time it encounters a fork in the road, and explores each road forward. Explore.

In DFS, we first need to explore the road in one direction. Currently, it is assumed that the left side is first and then the right side. Therefore, we always look for the left child of the node until the left node is empty (no left child), and then go to the right. Every time a new node is encountered, it must first traverse the left child and then the right child. For the non-recursive method, its difficulty is mainly the stacking and popping of nodes. When the tree structure is an array, we can use a visited array to save whether the node has been traversed, and whether the number of children visited is the same as the number of children of the node. But when the tree structure is a linked list, it is not so convenient to correspond to the marking bit.

(If you don’t understand this paragraph, just look at the code, I didn’t describe it very clearly) The main idea of ​​stacking and popping is that when traversing to the current node, it will judge whether it has a left (right) child node, and if it exists , it will Its left (right) child node is pushed onto the stack . The elements existing in the stack indicate that the left and right children of the node have not been visited or only the right child has not been visited. To meet this need, pop it out of the stack before starting to visit its right child node (starting access refers to judging whether the right child exists) . The condition for traversal termination is to see whether there are elements in the stack.

It is worth noting that the elements stored in the stack must first visit the left child, if the left child exists, continue, and if the left child does not exist, it will visit the right child. So here I added a judgment bit, "Whether the left side has been visited (isleft)". If the left side has been visited, the right side is visited, and the left side is not visited, the left side is visited. If the element is pushed in, isleft is set to false. If the element is popped out, isleft is set to true (due to the program flow design, the left child must have been visited in the pop stage).

Why should the node pop out before starting to judge whether the right child exists?
Because the nodes in the stack are all visited on the left side, what we will get is its right node, which is useless after visiting the right side. If you use the traditional method to visit the right child and then pop the parent node, you will not be able to distinguish it Have you ever visited.

example

insert image description here

accomplish

import java.util.*;
import java.util.Stack;
import java.util.ArrayList;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    
    
    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
    
    
        // write code here
        Stack<TreeNode> st1 = new Stack<TreeNode>();
        int isLeft=0;
        st1.push(t1);
        System.out.println(t1.val);
        while (st1.size()!=0){
    
    
            TreeNode pointer=st1.peek();
            if(isLeft==0){
    
    
                if(pointer.left!=null){
    
    
                    System.out.println(pointer.left.val);
                    st1.push(pointer.left);
                    isLeft=0;
                }else
                    isLeft=1;
            }
            else{
    
    
                st1.pop();
                isLeft=1;
                if(pointer.right!=null){
    
    
                    System.out.println(pointer.right.val);
                    st1.push(pointer.right);
                    isLeft=0;
                }
            }
        }
        return t1;
    }
}

at last

I know that my writing in this article is not clear. The original intention of writing this is to search the non-recursive method of DFS on the Internet, and all the obtained are fake dfs, that is, when traversing nodes, the left and right children are directly pushed into the stack instead of first left and then right. Friends who feel unclear after reading this article can communicate with me in the comment area. I hope that one day I can really understand technology.

Guess you like

Origin blog.csdn.net/ptyp222/article/details/120610288