Four traversal methods of tree (recursive and non recursive implementation c++&java)

Traversal of tree:

1. Preorder traversal

2. Middle order traversal

3. Post order traversal

4. Sequence traversal

1. Preorder traversal

        Preorder traversal, that is, DLR, first accesses the root node, then the left subtree, and then the right subtree. Therefore, traversal and backtracking are required

Recursion: recursively traverse the left subtree. While traversing, save the value of the node with the list, and save the traversed node with s. after going to the end, go back and visit the existing node of the previous node. Repeat the above process until the last node is accessed (both left and right are empty)

java:

class Solution {
    List<Integer> list=new ArrayList<Integer>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root==null) return list;
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return list;
    }
}

c++:

class Solution {
public:
    vector<int> res;
    vector<int> preorderTraversal(TreeNode* root) {
        if(root==NULL) return res;
        res.push_back(root->val);
        preorderTraversal(root->left);
        preorderTraversal(root->right);
        return res;
    }
};

Non recursive: in fact, there is a stack hidden in the recursive process. When using the non recursive method, we need to express the displayed stack and access the root node first. Therefore, during traversal, use list to save the value of the root node and a stack to save the root node until we access the bottom left node (i.e. node=null at this time), Then take out the nodes from the stack, continue to traverse each node, and repeat the process until the left and right children of the stack and nodes are empty

java:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<Integer>();
        if(root==null) return list;
        
        Deque<TreeNode> s=new LinkedList<TreeNode>();
        TreeNode node=root;
        while(!s.isEmpty()||node!=null){
            while(node!=null){
                list.add(node.val);
                s.push(node);
                node=node.left;
            }
            node=s.pop();
            node=node.right;
        }
        return list;
    }
}

c++: 

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL) return res;
        stack<TreeNode *> s;
        TreeNode* node=root;
        while(node!=NULL||!s.empty()){
            while(node!=NULL){
                res.push_back(node->val);
                s.push(node);
                node=node->left;
            }
            node=s.top();
            s.pop();
            node=node->right;
        }
        return res;
    }
};

2. Middle order traversal

         Middle order traversal is LDR. It also needs traversal and backtracking to access the left subtree, then the root node, and finally the right subtree

Recursion: starting from the root node, traverse the left subtree to the leftmost node and save the value of the node. Unlike the previous sequence traversal, the middle sequence traverses all the way to the leftmost node, then starts saving the value of the node, and then goes back

java:

class Solution {
    List<Integer> list=new ArrayList();
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root==null) return list;
        inorderTraversal(root.left);
        list.add(root.val);
        inorderTraversal(root.right);
        return list;
    }
}

c++: 

class Solution {
public:
    vector<int> res;
    vector<int> inorderTraversal(TreeNode* root) {
        
        if(root==NULL) return res;
        inorderTraversal(root->left);
        res.push_back(root->val);
        inorderTraversal(root->right);
        return res;
    }
};

Non recursive: the recursive process is the same as that of preorder traversal and inorder traversal, which also implies the call of a stack. When we iterate, we express the displayed stack, traversing from the root node to the bottom left node. In the traversal process, s is used to save the value of the node, and list is used to save the value of the node at the end of each traversal, And access the right node of the node and repeat the above process until the stack and the left and right children of the node are empty

java:

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        if(root==null) return list;
        Deque<TreeNode> s=new LinkedList();
        TreeNode node=root;
        while(node!=null||!s.isEmpty()){
            while(node!=null){
                s.push(node);
                node=node.left;
            }
            node=s.pop();
            list.add(node.val);
            node=node.right;
        }
        return list;
    }
}

c++: 

class Solution {
vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> res;
        while(!s.empty()||root!=NULL){
            while(root!=NULL){
                s.push(root);
                root=root->left;
            }
            TreeNode *pr=s.top();
            s.pop();
            res.push_back(pr->val);
            root=pr->right;
        }
        return res;
    }
};

3. Post order traversal

        Post order traversal, i.e. LRD, first accesses the left subtree, then the right subtree, and finally the root node. Therefore, traversal and backtracking are also required

Recursion: start from the root node, recursively access the left subtree, then recursively access the right subtree, and finally access the root node. Therefore, save the value of the node after each round of recursion

java:

class Solution {
    List<Integer> list=new ArrayList();
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root==null) return list;
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        list.add(root.val);
        return list;
    }
}

c++:

class Solution {
public:
    vector<int> res;
    vector<int> postorderTraversal(TreeNode* root) {
        if(root==NULL) return res;
        postorderTraversal(root->left);
        postorderTraversal(root->right);
        res.push_back(root->val);
        return res;
    }
};

Non recursive: post order traversal cannot only use stack backtracking like pre order and mid order traversal, because in the backtracking process, we do not know whether the previous node is a left node or a right node. We can access the root node only after accessing the right node. If it is a left node, we must access the right node first and then the root node. Therefore, We need to add an additional variable to save the last accessed node (prenode). If the right node of the node being accessed (curnode) is prenode or null, it means that the right node has been accessed or there is no right node, then we can save curnode directly. If not, we need to access the right node first. At the end of each access, we should modify the prenode to curnode

 java:

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        if(root==null) return list;
        Deque<TreeNode> s=new LinkedList();
        TreeNode preNode=null;
        TreeNode curNode=root;
        while(curNode!=null){
            s.push(curNode);
            curNode=curNode.left;
        }
        while(!s.isEmpty()){
            curNode=s.pop();
            if(curNode.right==null||curNode.right==preNode){
                list.add(curNode.val);
                preNode=curNode;
            }
            else{
                s.push(curNode);
                curNode=curNode.right;
                while(curNode!=null){
                    s.push(curNode);
                    curNode=curNode.left;
                }
            }
        }
        return list;
    }
}

c++:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        TreeNode *preNode=NULL;
        TreeNode *curNode=root;
        vector<int> res;
        if(root==NULL) return res;
        stack<TreeNode*> s;
        while(curNode!=NULL){
            s.push(curNode);
            curNode=curNode->left;
        }
        while(!s.empty()){
            curNode=s.top();
            s.pop();
            if(curNode->right==NULL||curNode->right==preNode){
                res.push_back(curNode->val);
                preNode=curNode;
            }
            else{
                s.push(curNode);
                curNode=curNode->right;
                while(curNode){
                    s.push(curNode);
                    curNode=curNode->left;
                }
            }
        }
        return res;
    }
};

4. Sequence traversal

        Sequence traversal is a layer by layer access, so there is no need to backtrack, but there needs to be a queue to save the current node value, so that the child node can be accessed through the node until the leaf node is accessed

java:

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        Queue<TreeNode> q=new LinkedList();
        if(root==null) return list;
        q.add(root);
        while(!q.isEmpty()){
            TreeNode p=q.poll();
            list.add(p.val);
            if(p.left!=null){
                q.add(p.left);
            }
            if(p.right!=null){
                q.add(p.right);
            }
        }
        return list;
    }
}

c++:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        queue<TreeNode*> q;
        vector<int> res;
        if(root==NULL) return res;
        q.push(root);
        while(!q.empty()){
            TreeNode *p=q.front();
            q.pop();
            res.push_back(p->val);
            if(p->left!=NULL) q.push(p->left);
            if(p->right!=NULL) q.push(p->right);
        }
        return res;
    }
};

In fact, non recursive can recite a template. I'm so smart

while(!s.empty()||root!=NULL){
            while(root!=NULL){
                s.push(root);
                root=root->left;
                //Add res.push here in the preamble_ back(pr->val);
            }
            TreeNode *pr=s.top();
            s.pop();
            //Add res.push here in the middle order_ back(pr->val);
            root=pr->right;
            //The next step is to judge the right node here and then do the corresponding operation
        }
        return res;

Finally finished. I hope I can help you. Welcome to leave messages and ask questions. If there are errors, please correct them. It's not easy to create. Thank you for your support

Tags: Java C++ data structure recursion

Posted on Wed, 22 Sep 2021 08:08:58 -0400 by pelleas